Chapter 5. Mobile Device Access

In this chapter, we will cover:

  • Getting your location

  • Handling cross-browser geolocation

  • Displaying a map based on your geolocation

  • Realtime positioning

  • DeviceOrientation event

  • Using geolocation with foursquare

Introduction

Among all the HTML5 classes, one that is most closely related to mobile development has to be Device Access.

Here is the official description of Device Access on the W3C HTML5 Movement site (http://www.w3.org/html/logo/):

Beginning with the Geolocation API, Web Applications can present rich, device-aware features, and experiences. Incredible device access innovations are being developed and implemented, from audio/video input access to microphones and cameras, to local data such as contacts and events, and even tilt orientation.

You can find the description and logo at: http://www.w3.org/html/logo/ #the-technology.

Location-based social networks like foursquare have had a profound impact on the way business works and how people mobilize. Groupon's new location-based offer, if it's released, may fundamentally change consumer behavior and the way retail businesses function. Google Maps uses realtime geolocation and GPRS to help people and vehicles navigate. There will be more and more exciting innovations built on top of this Device Access technology.

In this chapter, we will study geolocation API and DeviceOrientation API, address cross-browser issues, and see how we can use Device Access together with popular location-based services.

Getting your location

Target browsers: Android, iOS, webOS, Opera, Firefox

Using the geolocation API, we could return values like latitude, longitude, and accuracy of your current location:

  • Latitude and longitude: These attributes are geographic coordinates and are specified in decimal degrees

  • Accuracy: Denotes the accuracy level of the latitude and longitude coordinates and is specified in meters

Getting ready

Let's create an HTML document and get the latitude and longitude together with the accuracy. First, let's create a new HTML file, and name it ch05r01.html.

How to do it...

Enter the following code into the HTML document:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div id="main">
<div id="someElm">
</div>
</div>
<script src="http://code.jquery.com/jquery-1.5.2.min.js"></script>
<script>
function getLocation() {
navigator.geolocation.getCurrentPosition(showInfo);
}
function showInfo(position) {
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
var accuracy = position.coords.accuracy;
$('#someElm').html('latitude: '+latitude+'<br />longitude: '+longitude+'<br />accuracy: '+accuracy);
}
getLocation();
</script>
</body>
</html>

When you first render it, you will be prompted with a message as follows:

How to do it...

Geolocation support is opt-in. No browser will automatically send the physical location of your device to the server. Instead, it will ask for your permission before executing the program of sending the location of your device back and forth. The browser can remember your preference to prevent it from popping up again from the same site.

Now press the button that allows you to share the location. You will then get the location data displayed on the screen as follows:

How to do it...

How it works...

navigator is an object that is no stranger to JavaScript programmers. It's commonly used for user agent detection: navigator.userAgent.

geolocation is a new property on the navigator object: navigator.geolocation.

getCurrentPosition is a method of navigator.geolocation. In this example, we execute the function showInfo as the first argument:

navigator.geolocation.getCurrentPosition(showInfo);

In the showInfo function, we return three values from position parameter, that is, latitude, longitude, and accuracy:

var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
var accuracy = position.coords.accuracy;

There's more...

So, are the aforementioned attributes all that the geolocation API could return? Theoretically, more information can be returned, but in reality, only selected browsers will return additional information.

Handling cross-browser geolocation

Target browsers: cross-browser

Geolocation doesn't work on all mobile browsers, and even for those browsers that do support it, they could have an API that's different from the standard. iOS and Android use the standard. Browsers that are known to have a different API include Blackberry, Nokia, and Palm. Luckily, we have a mobile-centric geolocation polyfill&mdash;geo-location-javascript. It has non-standard Blackberry and webOS tricks to help normalize different API behaviors.

Getting ready

Download the resources that come with this chapter and create a js folder. Put geo.js into the js folder. Now create an HTML document named ch05r02.html.

How to do it...

Enter the following code into the HTML document:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="http://code.google.com/apis/gears/gears_init.js" type="text/javascript" charset="utf-8"></script>
<script src="js/geo.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="main">
<div id="someElm">
</div>
</div>
<script src="http://code.jquery.com/jquery-1.5.2.min.js"></script>
<script>
if(geo_position_js.init()){
geo_position_js.getCurrentPosition(success_callback,error_callback,{enableHighAccuracy:true,options:5000});
}
else{
$('#someElm').html("Functionality not available");
}
function success_callback(p)
{
$('#someElm').html('latitude: '+p.coords.latitude+'<br />longitude: '+p.coords.longitude+'<br />accuracy: '+p.coords.accuracy);
}
function error_callback(p)
{
$('#someElm').html('error='+p.message);
}
</script>
</body>
</html>

Test it in Opera and you should be able to see the result as follows:

How to do it...

How it works...

At the top of the HTML document, we link to gears_init.js. If the browser doesn't have a geolocation API supported by default, but has Gears installed, the Gears API may return the geolocation data. For browsers that have the geolocation API, but just in a different method, the second script geo.js will be used to normalize the API.

If geo_position_js.init() returns true, it means in one way or anther we are able to get the geolocation data. In this case we will proceed to the next step. Instead of using navigator.geolocation.getCurrentPosition, we use geo_position_js.getCurrentPosition as the method:

geo_position_js.getCurrentPosition(showInfo,error_callback,{enableHighAccuracy:true,options:5000});

There's more...

Here is an additional resource that will help you to get geolocation info.

YQL Geo Library

YQL Geo Library provides an alternative approach, an IP address-based geolocation. It is a lightweight library that is tied to Yahoo services. It can:

  • Get the geographical location from a text

  • Get the location information from lat/lon

  • Get all the geographical locations from a certain URL

  • Get the place from an IP number

Displaying a map based on your geolocation

Target browsers: cross-browser

The Google Maps API V3 has been designed to load fast and work well on mobile devices. In particular, we have focused on development for advanced mobile devices such as the iPhone and handsets running the Android operating system. Mobile devices have smaller screen sizes than typical browsers on the desktop. As well, they often have particular behavior specific to those devices, such as "pinch-to-zoom" on the iPhone.

Getting ready

Let's create a map that displays on your mobile device. First, let's create an HTML document named ch05r03.html.

How to do it...

Enter the following code:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true"></script>
<script src="http://code.google.com/apis/gears/gears_init.js"></script>
<script src="js/geo.js"></script>
<style>
html {
height: auto;
}
body {
height: auto;
margin: 0;
padding: 0;
}
#map_canvas {
height: auto;
position: absolute;
bottom:0;
left:0;
right:0;
top:0;
}
</style>
</head>
<body>
<div id="map_canvas"></div>
<script src="http://code.jquery.com/jquery-1.5.2.min.js"></script>
<script>
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: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
if(geo_position_js.init()){
browserSupportFlag = true;
geo_position_js.getCurrentPosition(function(position) {
initialLocation = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
contentString = "you are here";
map.setCenter(initialLocation);
infowindow.setContent(contentString);
infowindow.setPosition(initialLocation);
infowindow.open(map);
});
}
}
function detectBrowser() {
var useragent = navigator.userAgent;
var mapdiv = document.getElementById("map_canvas");
if (useragent.indexOf('iPhone') != -1 || useragent.indexOf('Android') != -1) {
mapdiv.style.width = '100%';
mapdiv.style.height = '100%';
} else {
mapdiv.style.width = '600px';
mapdiv.style.height = '800px';
}
}
detectBrowser();
initialize();
</script>
</body>
</html>

When rendered in your mobile browser, it looks as follows:

How to do it...

How it works...

Now let's break down the code and see what each section does:

  1. The iPhone has the pinch-to-zoom feature and Google Maps API V3 has special handling for this event. So you can set the following metatag and this will make sure that the users cannot resize the iPhone. Android devices running software version 1.5 (Cupcake) also support these parameters:

    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
    
  2. Set the<div> containing your map to have width and height attributes of 100 percent:

    mapdiv.style.width = '100%';
    mapdiv.style.height = '100%';
    
  3. You can detect iPhone and Android devices by inspecting the navigator.userAgent property within the DOM:

    function detectBrowser() {
    var useragent = navigator.userAgent;
    var mapdiv = document.getElementById("map_canvas");
    if (useragent.indexOf('iPhone') != -1 || useragent.indexOf('Android') != -1 ) {
    mapdiv.style.width = '100%';
    mapdiv.style.height = '100%';
    } else {
    mapdiv.style.width = '600px';
    mapdiv.style.height = '800px';
    }
    }
    
  4. Specifying the Sensor Parameter, applications that determine the user's location using a sensor must pass sensor=true when loading the Maps API JavaScript.

    <script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true"></script>
    

    Use of the Google Maps API requires that you indicate whether your application is using a sensor (such as a GPS locator) to determine the user's location. This is especially important for mobile devices. Applications must pass a required sensor parameter to the <script> tag when including the Maps API JavaScript code, indicating whether or not your application is using a sensor device.

    Note

    Note that even if we are targeting a device that does not use a sensing device, we must still pass this parameter, setting its value to false.

  5. We parse in the geolocation coordinates to the map API's LatLng method:

    initialLocation = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
    

There's more...

You can learn more about Google Maps JavaScript API V3 at the official documentation page at:

http://code.google.com/apis/maps/documentation/javascript/

HTML5 geolocation tutorial

Mobile tuts has an excellent article about mobile geolocation called HTML5 Apps: Positioning with Geolocation. You can read it at:

HTML5 Apps: Positioning with Geolocation

http://mobile.tutsplus.com/tutorials/mobile-web-apps/html5-geolocation/

Displaying location in realtime

Target browsers: cross-browser

Apart from getCurrentPosition, geolocation API has another method named watchPosition. It performs two important actions when called:

  1. It returns a value that identifies a watch operation.

  2. It asynchronously starts the watch operation.

Getting ready

Let's create an HTML document and name it ch05r04.html.

How to do it...

Enter the following code into the document:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style>
html {
height: auto;
}
body {
height: auto;
margin: 0;
padding: 0;
}
#map_canvas {
height: auto;
position: absolute;
bottom:0;
left:0;
right:0;
top:0;
}
</style>
</head>
<body>
<div id="map_canvas"></div>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true"></script>
<script src="http://code.jquery.com/jquery-1.5.2.min.js"></script>
<script>
var watchProcess = null;
var initialLocation;
var map;
var infowindow = new google.maps.InfoWindow();
var myOptions = {
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
navigator.geolocation.getCurrentPosition(function(position) {
updatePos(position.coords.latitude,position.coords.longitude,position.coords.accuracy);
});
initiate_watchlocation();
function initiate_watchlocation() {
if (watchProcess == null) {
watchProcess = navigator.geolocation.watchPosition(handle_geolocation_query, handle_errors);
}
}
function stop_watchlocation() {
if (watchProcess != null)
{
navigator.geolocation.clearWatch(watchProcess);
watchProcess = null;
}
}
locationdisplaying, in real timefunction handle_errors(error)
{
switch(error.code)
{
case error.PERMISSION_DENIED: alert("user did not share geolocation data");
break;
case error.POSITION_UNAVAILABLE: alert("could not detect current position");
break;
case error.TIMEOUT: alert("retrieving position timedout");
break;
default: alert("unknown error");
break;
}
}
function handle_geolocation_query(position) {
updatePos(position.coords.latitude,position.coords.longitude,position.coords.accuracy);
}
function updatePos(lat,long,acc) {
var text = "Latitude: " + lat + "<br/>" + "Longitude: " + long + "<br/>" + "Accuracy: " + acc + "m<br/>";
initialLocation = new google.maps.LatLng(lat,long);
contentString = text;
map.setCenter(initialLocation);
infowindow.setContent(contentString);
infowindow.setPosition(initialLocation);
infowindow.open(map);
}
</script>
</body>
</html>

Here is how it will be rendered:

How to do it...

How it works...

The following function will initiate the location watch:

function initiate_watchlocation() {
if (watchProcess == null) {
watchProcess = navigator.geolocation.watchPosition(handle_geolocation_query, handle_errors);
}
}

navigator.geolocation.watchPosition will either return success or error upon execution. In the success function, you can parse the latitude and longitude:

navigator.geolocation.watchPosition(handle_geolocation_query, handle_errors);

When the position is being watched, the handle_geolocation_query is used to get the current position and parse to the update position function:

function handle_geolocation_query(position) {
updatePos(position.coords.latitude,position.coords.longitude,position.coords.accuracy);
}

Using the DeviceOrientation event

Target browsers: iOS

The DeviceOrientation event is an important aspect of Device Access. It includes device motion events and device orientation events. Unfortunately, these events are currently supported in iOS only.

Getting ready

Create an HTML document and name it ch05r05.html.

How to do it...

Enter the following code into the document:

<!doctype html>
<html>
<head>
<title>Mobile Cookbook</title>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=true"></script>
<style>
#no {
display: none;
}
#ball {
width: 20px;
height: 20px;
border-radius: 10px;
background-color: red;
position:absolute;
top: 0px;
left: 0px;
}
</style>
</head>
<body>
<div id="content">
<h1>Move the Ball</h1>
<div id="yes">
<p>Move your device to move the ball.</p>
<div id="ball"></div>
</div>
<div id="no">
Your browser does not support Device Orientation and Motion API. Try this sample with iPhone, iPod or iPad with iOS 4.2+.</div>
</div>
<script>
// Position Variables
var x = 0;
var y = 0;
// Speed - Velocity
var vx = 0;
var vy = 0;
// Acceleration
var ax = 0;
var ay = 0;
var delay = 10;
var vMultiplier = 0.01;
if (window.DeviceMotionEvent==undefined) {
document.getElementById("no").style.display="block";
document.getElementById("yes").style.display="none";
} else {
window.ondevicemotion = function(event) {
ax = event.accelerationIncludingGravity.x;
ay = event.accelerationIncludingGravity.y;
}
setInterval(function() {
DeviceOrientation eventusingvy = vy + -(ay);
vx = vx + ax;
var ball = document.getElementById("ball");
y = parseInt(y + vy * vMultiplier);
x = parseInt(x + vx * vMultiplier);
if (x<0) { x = 0; vx = 0; }
if (y<0) { y = 0; vy = 0; }
if (x>document.documentElement.clientWidth-20) { x = document.documentElement.clientWidth-20; vx = 0; }
if (x>document.documentElement.clientWidth-20) { x = document.documentElement.clientWidth-20; vx = 0; }
if (y>document.documentElement.clientHeight-20) { y = document.documentElement.clientHeight-20; vy = 0; }
ball.style.top = y + "px";
ball.style.left = x + "px";
}, delay);
}
</script>
</body>
</html>

How it works...

This code was made by Maximiliano Firtman (http://www.mobilexweb.com/blog/safari-ios-accelerometer-websockets-html5). In the example, we used accelerationIncludingGravity. It returns the value of the total acceleration of the device, which includes the user acceleration and the gravity.

The three values, x, y, z, represent the acceleration in m/s^2 for each axis:

window.ondevicemotion = function(event) {
event.accelerationIncludingGravity.x
event.accelerationIncludingGravity.y
event.accelerationIncludingGravity.z
}
How it works...

There's more...

Here is a table that shows the current support for DeviceOrientationEvent and DeviceMotionEvent:

Properties

Description

Returned values

Class

Support

acceleration

The acceleration that the user is giving to the device.

x, y, z (in m/s^2)

DeviceMotion Event

iPhone 4 / iPod Touch 4G

acceleration IncludingGravity

The total acceleration of the device, which includes the user acceleration and the gravity.

x, y, z (in m/s^2)

DeviceMotion Event

iPhone3 / iPod Touch 3G

interval

The interval in milliseconds since the last device motion event.

milliseconds

DeviceMotion Event

iPhone3 / iPod Touch 3G

rotationRate

The rotation rate of the device.

alpha, beta, and gamma (values are between 0 and 360)

DeviceMotionEvent

iPhone 4 / iPod Touch 4G

alpha

The degrees the device frame is rotated around its z-axis.

Values are between 0 and 360.

DeviceOrientation Event

iPhone 4 / iPod Touch 4G

beta

The degrees the device frame is rotated around its x-axis.

Values are between -180 and 180.

DeviceOrientation Event

iPhone 4 / iPod Touch 4G

gamma

The degrees the device frame is rotated around its y-axis.

Values are between -90 and 90.

DeviceOrientation Event

iPhone 4 / iPod Touch 4G

DeviceOrientation event specification

http://dev.w3.org/geo/api/spec-source-orientation.html

Using geolocation with foursquare

Target browsers: cross-browser

In recent years, the location-based social networking website foursquare has become more and more popular. It affected the way many business work and consumers behave. Users "check-in" at places using a mobile website, mobile app, or SMS.

Getting ready

Third-party developers have released many libraries for accessing the foursquare API from various programming languages. One of those is Marelle. It's based on jQuery and written in coffeescript. Don't worry, that's just JavaScript.

How to do it...

Go to the GitHub page of Marelle (http://praized.github.com/marelle/) and download the latest version. There are two examples, one is login and another is check-in.

Here is what the login script looks like:

// Supply your foursquare client id
var FSQUARE_CLIENT_ID = 'FOURSQUARE_CLIENT_ID';
// on DOM ready...
$(function() {
// setup with your key and a callback function which
// receives the Marelle Object ( "M" in this example )
$.Marelle( FSQUARE_CLIENT_ID ).done( function( M ){
// grab an authentication promise
var authpromise = M.authenticateVisitor();
// handle logged-in visitor
var authsuccess = function(visitor){
M.signoutButton( document.body );
console.log(visitor)
/*
I think the single entry point is through the visitor
*/
venuepromise = visitor.getVenues()
// venuepromise.then etc..etc...
};
// handle non visitor
var authfailure = function() {
M.signinButton( document.body );
};
// wait for promise to resolve
authpromise.then(authsuccess,authfailure)
}).fail(function(){
consoloe.log('Marelle could not be loaded.')
});
});

How it works...

Here's how it works:

  1. First we trigger Marelle initialization $.Marelle(clientID) and it returns a promise:

    $.Marelle( FSQUARE_CLIENT_ID )
    
  2. Then we grab an authentication promise using $.Marelle.authenticateVisitor():

    $.Marelle( FSQUARE_CLIENT_ID ).done( function( M ){
    var authpromise = M.authenticateVisitor();
    });
    
  3. Depending on the result of the authentication, authpromise.then() is used to either execute authsuccess or authfailure:

    authpromise.then(authsuccess,authfailure)
    
  4. If the authentication is successful, it appends a "disconnect" button to the provided selector:

    M.signoutButton( document.body );
    
  5. One can return a list of recommended venues, add or search venues:

    venuepromise = visitor.getVenues()
    
  6. If the authentication is unsuccessful, it appends a "Connect" button to the provided selector:

    M.signinButton( document.body );
    

There's more..

A list of foursquare APIs can be found at:

https://developer.foursquare.com/docs/libraries.html

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset