Using Location Data with PhoneGap

Packt Publishing

PhoneGap opens up mobile application development to more people by using HTML and JavaScript. This book gives you the know-how on all the essentials in friendly, example-driven tutorials that will empower you to do more.

An introduction to Geolocation

The term geolocation is used in order to refer to the identification process of the real-world geographic location of an object. Devices that are able to detect the user's position are becoming more common each day and we are now used to getting content based on our location ( geo targeting ).

Using the Global Positioning System (GPS )—a space-based satellite navigation system that provides location and time information consistently across the globe—you can now get the accurate location of a device. During the early 1970s, the US military created Navstar, a defense navigation satellite system. Navstar was the system that created the basis for the GPS infrastructure used today by billions of devices. Since 1978 more than 60 GPS satellites have been successfully placed in the orbit around the Earth (refer to http://en.wikipedia.org/wiki/List_of_GPS_satellite_launches for a detailed report about the past and planned launches).

The location of a device is represented through a point. This point is comprised of two components: latitude and longitude. There are many methods for modern devices to determine the location information, these include:

Global Positioning System (GPS)

IP address

GSM/CDMA cell IDs

Wi-Fi and Bluetooth MAC address

Each approach delivers the same information; what changes is the accuracy of the device's position. The GPS satellites continuously transmit information that can parse, for example, the general health of the GPS array, roughly, where all of the satellites are in orbit, information on the precise orbit or path of the transmitting satellite, and the time of the transmission. The receiver calculates its own position by timing the signals sent by any of the satellites in the array that are visible.

The process of measuring the distance from a point to a group of satellites to locate a position is known as trilateration . The distance is determined using the speed of light as a constant along with the time that the signal left the satellites.

The emerging trend in mobile development is GPS-based "people discovery" apps such as Highlight, Sonar, Banjo, and Foursquare. Each app has different features and has been built for different purposes, but all of them share the same killer feature: using location as a piece of metadata in order to filter information according to the user's needs.

The PhoneGap Geolocation API

The Geolocation API is not a part of the HTML5 specification but it is tightly integrated with mobile development. The PhoneGap Geolocation API and the W3C Geolocation API mirror each other; both define the same methods and relative arguments. There are several devices that already implement the W3C Geolocation API; for those devices you can use native support instead of the PhoneGap API.

As per the HTML specification, the user has to explicitly allow the website or the app to use the device's current position.

The Geolocation API is exposed through the geolocation object child of the navigator object and consists of the following three methods:

getCurrentPosition() returns the device position.

watchPosition() watches for changes in the device position.

clearWatch() stops the watcher for the device's position changes.

The watchPosition() and clearWatch() methods work in the same way that the setInterval() and clearInterval() methods work; in fact the first one returns an identifier that is passed in to the second one. The getCurrentPosition() and watchPosition() methods mirror each other and take the same arguments: a success and a failure callback function and an optional configuration object. The configuration object is used in order to specify the maximum age of a cached value of the device's position, to set a timeout after which the method will fail and to specify whether the application requires only accurate results.

Only the first argument is mandatory; but it's recommended to handle always the failure use case.

The success handler function receives as argument, a Position object. Accessing its properties you can read the device's coordinates and the creation timestamp of the object that stores the coordinates.

The coords property of the Position object contains a Coordinates object; so far the most important properties of this object are longitude and latitude. Using those properties it's possible to start to integrate positioning information as relevant metadata in your app.

The failure handler receives as argument, a PositionError object. Using the code and the message property of this object you can gracefully handle every possible error.

PositionError.TIMEOUT, the specified timeout has elapsed before the implementation could successfully acquire a new Position object

JavaScript doesn't support constants such as Java and other object-oriented programming languages. With the term "pseudo constants", I refer to those values that should never change in a JavaScript app.

One of the most common tasks to perform with the device position information is to show the device location on a map. You can quickly perform this task by integrating Google Maps in your app; the only requirement is a valid API key. To get the key, use the following steps:

Open the command-line tool, build the app, and then run it on your testing devices.

$ cordova build$ cordova run android

What just happened?

You integrated Google Maps inside an app. The map is an interactive map most users are familiar with—the most common gestures are already working and the Google Street View controls are already enabled.

To successfully load the Google Maps API on iOS, it's mandatory to whitelist the googleapis.com and gstatic.com domains. Open the .plist file of the project as source code (right-click on the file and then Open As | Source Code ) and add the following array of domains:

Other Geolocation data

In the previous example, you only used the latitude and longitude properties of the position object that you received. There are other attributes that can be accessed as properties of the Coordinates object:

altitude, the height of the device, in meters, above the sea level.

accuracy, the accuracy level of the latitude and longitude, in meters; it can be used to show a radius of accuracy when mapping the device's position.

altitudeAccuracy, the accuracy of the altitude in meters.

heading, the direction of the device in degrees clockwise from true north.

speed, the current ground speed of the device in meters per second.

Latitude and longitude are the best supported of these properties, and the ones that will be most useful when communicating with remote APIs. The other properties are mainly useful if you're developing an application for which Geolocation is a core component of its standard functionality, such as apps that make use of this data to create a flow of information contextualized to the geolocation data. The accuracy property is the most important of these additional features, because as an application developer, you typically won't know which particular sensor is giving you the location and you can use the accuracy property as a range in your queries to external services.

There are several APIs that allow you to discover interesting data related to a place; among these the most interesting are the Google Places API and the Foursquare API.

The itinero reference app for this article implements both the APIs. In the next example, you will look at how to integrate Google Places inside the RequireJS app.

In order to include the Google Places API inside an app, all you have to do is add the libraries parameter to the Google Maps API call. The resulting URL should look similar to http://maps.google.com/maps/api/js?key=SECRET_KEY&sensor=true&libraries=places.

The itinero app lets users create and plan a trip with friends. Once the user provides the name of the trip, the name of the country to be visited, and the trip mates and dates, it's time to start selecting the travel, eat, and sleep options.

When the user selects the Eat option, the Google Places data provider will return bakeries, take-out places, groceries, and so on, close to the trip's destination. The app will show on the screen a list of possible places the user can select to plan the trip.

Go to the js/utils folder and create a new RequireJS module named gmaps. This module allows your app to download the Google Places API only when requested by another module; use the module's name to access the Google Maps API.

Create a new Mustache template named create-find-places-tpl.html to show to the user the available data providers (i.e. Google and FourSquare), to search for and return places in the selected city/country, and to save it in the tpl folder.

Create a new RequireJS module named FindPlaceView.js, define its dependencies, and save it into the js/views/create/findplaces folder (the module uses the templateProvider utility to load a new template, Mustache to add the results on the screen, and the spinner utility to show when the app is loading new data). The content of the file will look like the following snippet of code.

Create another RequireJS module named FindPlaces.js with an explicit dependency to the module FindPlaceView.js and save it into the js/controllers folder. The content of the file will look like the following snippet of code:

Open the FindPlaces.js module and define a function to init the module and another one to start it and expose both functions using a return object. The init function stores the data needed by the template and the city used as search target; the start function initializes the view. The init function also registers a listener in order to enable the interactivity on the Google Places and Foursquare selectors only when the template is loaded.

Define the onInitFinders listener and add to its body a call to the Array.prototype.forEach method in order to define the click event listener for all the <a> tags used to render the data provider options.

Open the FindPlaceView.js module previously created, define the render function, and expose it using the return object. The render function loads a new template and defines a listener for the templateReady event.

Define the onTemplateReady function in the FindPlaceView.js file and inside its body add the code needed to populate the template and to notify the FindPlaces.js controller that it can define the listeners for the data source selectors.

In the same file, add the function to load the data using the Google Places API. The first thing the function has to do is to require the gmaps module already defined and waiting until the API is available.

function loadFromGoogle() {
require(['utils/gmaps'], function(gmaps){
// Do some stuff when the API is available
});
}

When the API is available, the anonymous function used as an argument in the require function has to create a new Geocoder object in order to recover the latitude and longitude of the target city. The Geocoder object is created in the js/controllers/FindPlaces.js file.

When the value of the status argument used within the geocode method handler is OK you can recover the latitude and the longitude needed to define the center of the map to be used to perform the places search.

Inside the conditional statement, add a request object to specify the center of the request, the radius, and the types of places. Use the object to start a Nearby Search (a search for places within a specified area by keyword or type) and define a listener for the results.

Create the onResult function. The function receives two arguments, one is the search result and the other is the status of the research; according to the request status, populate the places property of the currentData object and then populate the view with the recovered data.

What just happened?

The itinero app is now able to get information about places near the destination of the trip and the user can now add them to the trip's plan and notes.

Summary

In this article, you learned how to get the Geolocation information from a device and how to integrate external Geolocation service in the app. In the next article, you will learn how to manipulate a file, access the device Camera, and perform some basic image manipulation.

Alerts & Offers

Series & Level

We understand your time is important. Uniquely amongst the major publishers, we seek to develop and publish the broadest range of learning and information products on each technology. Every Packt product delivers a specific learning pathway, broadly defined by the Series type. This structured approach enables you to select the pathway which best suits your knowledge level, learning style and task objectives.

Learning

As a new user, these step-by-step tutorial guides will give you all the practical skills necessary to become competent and efficient.

Beginner's Guide

Friendly, informal tutorials that provide a practical introduction using examples, activities, and challenges.

Essentials

Fast paced, concentrated introductions showing the quickest way to put the tool to work in the real world.

Cookbook

A collection of practical self-contained recipes that all users of the technology will find useful for building more powerful and reliable systems.

Blueprints

Guides you through the most common types of project you'll encounter, giving you end-to-end guidance on how to build your specific solution quickly and reliably.

Mastering

Take your skills to the next level with advanced tutorials that will give you confidence to master the tool's most powerful features.

Starting

Accessible to readers adopting the topic, these titles get you into the tool or technology so that you can become an effective user.

Progressing

Building on core skills you already have, these titles share solutions and expertise so you become a highly productive power user.