Part 7: Add GPS Reading

Ok, so now we have created a PhoneGap compass application with an arrow that always points to the North. Next, we’ll also add to this the latitude and longitude readings of our current position. For this we’ll need to add to the project the geolocation plugin

cordova plugin add org.apache.cordova.geolocation

to which the response should be (assuming you’ve only created an android project):

Fetching plugin from "org.apache.cordova.geolocation"...
Starting installation of "org.apache.cordova.geolocation" for android
Preparing android project
org.apache.cordova.geolocation installed on android.

If you now type:
cordova plugin ls

you should see:

[ 'org.apache.cordova.device-orientation',
  'org.apache.cordova.geolocation' ]

Since our compass project uses these two plugins.


The next part is to add the JavaScript code that reads the current coordinates from the GPS sensor on the smartphone.

Temporarily, just to see that the application is indeed trying to get the GPS coordinates, we’ll change in the config.xml file from:

<preference name="fullscreen" value="true" />

to

<preference name="fullscreen" value="false" />

This will enable us to see on Android the device status bar and verify that the application is indeed trying to get a fix on it’s location via the GPS (you should ensure that the GPS is indeed turned on)

The API for the geolocation plugin can be viewed in the Cordova plugin reference documentation, but the code below (which should replace our previous index.html) should be self explanatory:

<!DOCTYPE html>
<html>
<head>
<title>Compass Example</title>

<script type="text/javascript" charset="utf-8" src="cordova.js"></script>
<script type="text/javascript" charset="utf-8">

var g_PI2       = Math.PI*2; // 2 x Pi
var g_toRAD     = 360/g_PI2; // Divide degrees by this to get radians
var g_watchH    = null;      // the current watchHeading (compass) callback identifier
var g_watchG    = null;      // the current watchPosition (GPS) callback identifier
var g_ArrHeight = 48;        // Height of drawn arrow

// Wait for device API libraries to load
//
document.addEventListener("deviceready", onDeviceReady, false);

// device APIs are available, we can now access the sensor plugins
//
function onDeviceReady()
{
    var oc = document.getElementById('arrow');
    // Set the size of the canvas
    oc.width  = g_ArrHeight * 4;
    oc.height = g_ArrHeight * 4;        
    startWatchH(); // start monitoring the compass
    startWatchG(); // start monitoring the GPS
}

// Start monitoring the compass
//
function startWatchH()
{
    // Update compass every 3 seconds
    var options = { frequency: 250 };
    g_watchH = navigator.compass.watchHeading(onSuccessH, onErrorH, options);
}


// Stop monitoring the compass
//
function stopWatchH()
{
    if (g_watchH)
        return;

    if (g_watchH) {
        navigator.compass.clearWatch(g_watchH);
        g_watchH = null;
    }
}

// Start monitoring the GPS
//
function startWatchG()
{
    // enableHighAccuracy:true will require the use of the GPS sensor
    if (g_watchG)
        return;

    var options = { maximumAge: 3000, timeout: 5000, enableHighAccuracy: true }
    g_watchG = navigator.geolocation.watchPosition(onSuccessG, onErrorG, options);
}

// Stop monitoring the GPS
//
function stopWatchG()
{
    if (g_watchG) {
        navigator.geolocation.clearWatch(g_watchG);
        g_watchG = null;
    }
}

// onSuccessH: Get the current compass heading
//
function onSuccessH(heading)
{
    var element = document.getElementById('heading');
    element.innerHTML = 'Heading: ' + heading.magneticHeading;
    // We want the arrow to point to the same position (North) regardless
    // of the device orientation, so since the North heading is given 
    // relative to the top of the device, we'll point the arrow to
    // 2xPi (360 degrees) minus the heading of the top of the device.
    drawArrow(g_PI2-heading.magneticHeading/g_toRAD);
}

// onSuccessG: Get the current position from GPS
//
function onSuccessG(position)
{
    var element = document.getElementById('geolocation');
    element.innerHTML = 'Latitude: '  + position.coords.latitude  + '<br />' +
                        'Longitude: ' + position.coords.longitude
}

// onError: Failed to get the compass heading
//
function onErrorH(compassError)
{
    writeError( 'heading_error', compassError);
}

// onError: Failed to get the GPS data
//
function onErrorG(positionError)
{
    writeError( 'geolocation_error', positionError);
}

function writeError(id, err)
{
    var msg = "Code:" + err.code + ", message:" + err.message;
    document.getElementById(id).innerHTML = msg;
}

function drawArrow(r)
{
    var ctx = document.getElementById('arrow').getContext('2d');
    ctx.clearRect(0, 0, g_ArrHeight*4, g_ArrHeight*4);
    var state = ctx.save();
    var fulld3 = g_ArrHeight/3;
    var fulld2 = g_ArrHeight/2;
    ctx.translate(g_ArrHeight*2, g_ArrHeight*2);
    ctx.rotate(r);

    ctx.beginPath();
    ctx.strokeStyle = '#aaaaff';
    ctx.lineWidth = 5;

    ctx.moveTo(0, -g_ArrHeight);
    ctx.lineTo(g_ArrHeight, fulld3);
    ctx.lineTo(fulld2, fulld3);
    ctx.lineTo(fulld2, g_ArrHeight);
    ctx.lineTo(-fulld2, g_ArrHeight);
    ctx.lineTo(-fulld2, fulld3);
    ctx.lineTo(-g_ArrHeight, fulld3);

    ctx.closePath();
    ctx.stroke();
    ctx.fillStyle="#33ff33";
    ctx.fill();

    ctx.restore(state);
}
</script>
</head>
<body>
<div id="geolocation">Waiting for position...</div>
<button onclick="startWatchG();">Start Watching GPS</button>
<button onclick="stopWatchG();">Stop Watching GPS</button>

<br /><hr />

<div id="heading">Waiting for heading...</div>
<button onclick="startWatchH();">Start Watching Compass</button>
<button onclick="stopWatchH();">Stop Watching Compass</button>

<br /><hr />

<canvas id="arrow"></canvas>

<div id="geolocation_error"></div>
<div id="heading_error"></div>

</body>
</html>

As usual, connect the Android device via USB cable to your PC and

cordova build android
cordova run android

One Comment

  1. Temporarily, just to see that the application is indeed trying to get the GPS coordinates, we’ll change in the config.xml file from:

    to

    Can’t find this in my config.xml file

    compass

    A sample Apache Cordova application that responds to the deviceready event.

    Apache Cordova Team

Leave a Reply

Your email address will not be published. Required fields are marked *