PhoneGap with GoogleMaps

It is possible to get the current location of a mobile device. This can be used with GoogleMaps to provide localised mapping apps.

Geolocation Core Plugin

PhoneGap has a Geolocation plugin, which can be used to obtain the latitude and longitude of the current location.

Click here to download a .zip containing an example app that shows the current position's latitude and longitude (this app is called e120).

config.xml

<widget  xmlns="http://cordova.apache.org/ns/1.0"
version="1.0.0"
id="ie.dkit.derek_e120" > <name>e120</name> <description>Demo with Geolocation</description> <author email="derek.oreilly@dkit.ie" href="http://derek.dkit.ie">Derek O Reilly</author> <platform name="ios"> <icon src="res/icons/ios/icon-1024.png" width="1024" height="1024"/> <icon src="res/icons/ios/icon-small.png" width="29" height="29"/> <icon src="res/icons/ios/icon-small@2x.png" width="58" height="58"/> <icon src="res/icons/ios/icon-small@3x.png" width="87" height="87"/> <icon src="res/icons/ios/icon-small-40.png" width="40" height="40"/> <icon src="res/icons/ios/icon-small-40@2x.png" width="80" height="80"/> <icon src="res/icons/ios/icon-small-40@3x.png" width="120" height="120"/> <icon src="res/icons/ios/icon-small-50.png" width="50" height="50"/> <icon src="res/icons/ios/icon-small-50@2x.png" width="100" height="100"/> <icon src="res/icons/ios/icon.png" width="57" height="57"/> <icon src="res/icons/ios/icon@2x.png" width="114" height="114"/> <icon src="res/icons/ios/icon-60.png" width="60" height="60"/> <icon src="res/icons/ios/icon-60@2x.png" width="120" height="120"/> <icon src="res/icons/ios/icon-60@3x.png" width="180" height="180"/> <icon src="res/icons/ios/icon-72.png" width="72" height="72"/> <icon src="res/icons/ios/icon-72@2x.png" width="144" height="144"/> <icon src="res/icons/ios/icon-76.png" width="76" height="76"/> <icon src="res/icons/ios/icon-76@2x.png" width="152" height="152"/> <icon src="res/icons/ios/icon-167.png" width="167" height="167"/> <icon src="res/icons/ios/icon-83.5@2x.png" width="167" height="167"/> <splash src="res/screens/ios/Default~iphone.png" width="320" height="480"/> <splash src="res/screens/ios/Default@2x~iphone.png" width="640" height="960"/> <splash src="res/screens/ios/Default-Portrait~ipad.png" width="768" height="1024"/> <splash src="res/screens/ios/Default-Portrait@2x~ipad.png" width="1536" height="2048"/> <splash src="res/screens/ios/Default-568h@2x~iphone.png" width="640" height="1136"/> <splash src="res/screens/ios/Default-667h.png" width="750" height="1334"/> <splash src="res/screens/ios/Default-736h.png" width="1242" height="2208"/> </platform> <platform name="android"> <icon density="ldpi" src="res/icons/android/ldpi.png"/> <icon density="mdpi" src="res/icons/android/mdpi.png"/> <icon density="hdpi" src="res/icons/android/hdpi.png"/> <icon density="xhdpi" src="res/icons/android/xhdpi.png"/> <icon density="xxhdpi" src="res/icons/android/xxhdpi.png"/> <icon density="xxxhdpi" src="res/icons/android/xxxhdpi.png"/> <splash density="port-ldpi" src="res/screens/android/splash-port-ldpi.png"/> <splash density="port-mdpi" src="res/screens/android/splash-port-mdpi.png"/> <splash density="port-hdpi" src="res/screens/android/splash-port-hdpi.png"/> <splash density="port-xhdpi" src="res/screens/android/splash-port-xhdpi.png"/> <splash density="port-xxhdpi" src="res/screens/android/splash-port-xxhdpi.png"/> <splash density="port-xxxhdpi" src="res/screens/android/splash-port-xxxhdpi.png"/> </platform> <platform name="windows"> <icon src="res/icons/windows/storelogo.png" target="StoreLogo" /> <icon src="res/icons/windows/smalllogo.png" target="Square30x30Logo" /> <icon src="res/icons/windows/Square44x44Logo.png" target="Square44x44Logo" /> <icon src="res/icons/windows/Square70x70Logo.png" target="Square70x70Logo" /> <icon src="res/icons/windows/Square71x71Logo.png" target="Square71x71Logo" /> <icon src="res/icons/windows/Square150x150Logo.png" target="Square150x150Logo" /> <icon src="res/icons/windows/Square310x310Logo.png" target="Square310x310Logo" /> <splash src="res/screens/windows/splashscreen.png" target="SplashScreen"/> <splash src="res/screens/windows/splashscreenphone.png" target="SplashScreenPhone"/> </platform> <preference name="DisallowOverscroll" value="true" /> <!-- ios: stop overscroll/bounce --> <preference name="orientation" value="portrait" /> <!-- all: default means both landscape and portrait are enabled --> <preference name="fullscreen" value="true" /> <!-- all: hides the status bar at the top of the screen --> <preference name="exit-on-suspend" value="true" /> <!-- ios: if set to true, app will terminate when home button is pressed --> <config-file platform="ios" parent="UIViewControllerBasedStatusBarAppearance" overwrite="true"> <false/> <!-- true = show status bar, false = hide status bar --> </config-file> <plugin name="cordova-plugin-geolocation" spec="~2.4.3" /> <!-- Allow access various files that relate to the GoogleMaps API --> <access origin="*" /> </widget>

 

index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="initial-scale=1, width=device-width, height=device-height, viewport-fit=cover">
<title>Geolocation Demo</title>

<!-- This is needed to access the PhoneGap JavaScript -->
<script type="text/javascript" charset="utf-8" src="cordova.js"></script>

<script>
window.onload = onAllAssetsLoaded;
document.write("<div id='loadingMessage'>Loading...</div>");
function onAllAssetsLoaded()
{
    // Wait for Cordova to connect with the device
    document.addEventListener("deviceready", onDeviceReady, false);
}

// Cordova is ready to be used!
function onDeviceReady()
{
    // note, it takes a few seconds for the gps to work, so you need to give a high timeout value
    let options = {maximumAge: 1000, timeout: 50000, enableHighAccuracy: true};
    navigator.geolocation.getCurrentPosition(onGeolocationSuccess, onGeolocationError, options);
}


function onGeolocationSuccess(position)
{
    document.getElementById('geolocationDetails').innerHTML = 'Latitude: ' + position.coords.latitude + '<br>' +
            'Longitude: ' + position.coords.longitude + '<br>' +
            'Altitude: ' + position.coords.altitude;
}


function onGeolocationError(error)
{
    document.getElementById('geolocationDetails').innerHTML = 'code: ' + error.code + '<br>' +
            'message: ' + error.message + '<br>';
}
</script>
</head>

<body>
<h1>Geolocation Demo</h1>
<p id="geolocationDetails">Finding geolocation...</p>
</body>
</html>

Google Map Current Position

Click here to download a .zip containing an example app that shows a map centered on the current position (this app is called e121).

config.xml

<widget  xmlns="http://cordova.apache.org/ns/1.0"
version="1.0.0"
id="ie.dkit.derek_e121" > <name>e121</name> <description>Demo with Geolocation Map of Current Location</description> <author email="derek.oreilly@dkit.ie" href="http://derek.dkit.ie">Derek O Reilly</author> <platform name="ios"> <icon src="res/icons/ios/icon-1024.png" width="1024" height="1024"/> <icon src="res/icons/ios/icon-small.png" width="29" height="29"/> <icon src="res/icons/ios/icon-small@2x.png" width="58" height="58"/> <icon src="res/icons/ios/icon-small@3x.png" width="87" height="87"/> <icon src="res/icons/ios/icon-small-40.png" width="40" height="40"/> <icon src="res/icons/ios/icon-small-40@2x.png" width="80" height="80"/> <icon src="res/icons/ios/icon-small-40@3x.png" width="120" height="120"/> <icon src="res/icons/ios/icon-small-50.png" width="50" height="50"/> <icon src="res/icons/ios/icon-small-50@2x.png" width="100" height="100"/> <icon src="res/icons/ios/icon.png" width="57" height="57"/> <icon src="res/icons/ios/icon@2x.png" width="114" height="114"/> <icon src="res/icons/ios/icon-60.png" width="60" height="60"/> <icon src="res/icons/ios/icon-60@2x.png" width="120" height="120"/> <icon src="res/icons/ios/icon-60@3x.png" width="180" height="180"/> <icon src="res/icons/ios/icon-72.png" width="72" height="72"/> <icon src="res/icons/ios/icon-72@2x.png" width="144" height="144"/> <icon src="res/icons/ios/icon-76.png" width="76" height="76"/> <icon src="res/icons/ios/icon-76@2x.png" width="152" height="152"/> <icon src="res/icons/ios/icon-167.png" width="167" height="167"/> <icon src="res/icons/ios/icon-83.5@2x.png" width="167" height="167"/> <splash src="res/screens/ios/Default~iphone.png" width="320" height="480"/> <splash src="res/screens/ios/Default@2x~iphone.png" width="640" height="960"/> <splash src="res/screens/ios/Default-Portrait~ipad.png" width="768" height="1024"/> <splash src="res/screens/ios/Default-Portrait@2x~ipad.png" width="1536" height="2048"/> <splash src="res/screens/ios/Default-568h@2x~iphone.png" width="640" height="1136"/> <splash src="res/screens/ios/Default-667h.png" width="750" height="1334"/> <splash src="res/screens/ios/Default-736h.png" width="1242" height="2208"/> </platform> <platform name="android"> <icon density="ldpi" src="res/icons/android/ldpi.png"/> <icon density="mdpi" src="res/icons/android/mdpi.png"/> <icon density="hdpi" src="res/icons/android/hdpi.png"/> <icon density="xhdpi" src="res/icons/android/xhdpi.png"/> <icon density="xxhdpi" src="res/icons/android/xxhdpi.png"/> <icon density="xxxhdpi" src="res/icons/android/xxxhdpi.png"/> <splash density="port-ldpi" src="res/screens/android/splash-port-ldpi.png"/> <splash density="port-mdpi" src="res/screens/android/splash-port-mdpi.png"/> <splash density="port-hdpi" src="res/screens/android/splash-port-hdpi.png"/> <splash density="port-xhdpi" src="res/screens/android/splash-port-xhdpi.png"/> <splash density="port-xxhdpi" src="res/screens/android/splash-port-xxhdpi.png"/> <splash density="port-xxxhdpi" src="res/screens/android/splash-port-xxxhdpi.png"/> </platform> <platform name="windows"> <icon src="res/icons/windows/storelogo.png" target="StoreLogo" /> <icon src="res/icons/windows/smalllogo.png" target="Square30x30Logo" /> <icon src="res/icons/windows/Square44x44Logo.png" target="Square44x44Logo" /> <icon src="res/icons/windows/Square70x70Logo.png" target="Square70x70Logo" /> <icon src="res/icons/windows/Square71x71Logo.png" target="Square71x71Logo" /> <icon src="res/icons/windows/Square150x150Logo.png" target="Square150x150Logo" /> <icon src="res/icons/windows/Square310x310Logo.png" target="Square310x310Logo" /> <splash src="res/screens/windows/splashscreen.png" target="SplashScreen"/> <splash src="res/screens/windows/splashscreenphone.png" target="SplashScreenPhone"/> </platform> <preference name="DisallowOverscroll" value="true" /> <!-- ios: stop overscroll/bounce --> <preference name="orientation" value="portrait" /> <!-- all: default means both landscape and portrait are enabled --> <preference name="fullscreen" value="true" /> <!-- all: hides the status bar at the top of the screen --> <preference name="exit-on-suspend" value="true" /> <!-- ios: if set to true, app will terminate when home button is pressed --> <config-file platform="ios" parent="UIViewControllerBasedStatusBarAppearance" overwrite="true"> <false/> <!-- true = show status bar, false = hide status bar --> </config-file> <plugin name="cordova-plugin-geolocation" spec="~2.4.3" /> <!-- Allow access various files that relate to the GoogleMaps API --> <access origin="*" /> </widget>

 

index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="initial-scale=1, width=device-width, height=device-height, viewport-fit=cover">
<title>Geolocation Demo</title>
<style>
*
{
    -webkit-touch-callout: none;  /* Disable element selection in app */
    -webkit-user-select: none;    /* Disable text selection in app */ 
}

html, 
body, 
#geolocationDetails 
{
    width:100%;
    height:100%;
    margin:0px;
    padding:0px;
}

h3,
p
{
    margin:5px;
}

#mapType
{
    position:absolute;
    bottom:10px;
    right:10px;
    visibility:hidden;
}
</style>

<!-- This is needed to access the PhoneGap JavaScript -->
<script type="text/javascript" charset="utf-8" src="cordova.js"></script>

<!-- Google Maps -->
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>

<script>
let currentLocationMap;
window.onload = onAllAssetsLoaded;
document.write("<div id='loadingMessage'>Loading...</div>");
function onAllAssetsLoaded()
{
    // Wait for Cordova to connect with the device
    document.addEventListener("deviceready", onDeviceReady, false);
}

// Cordova is ready to be used!
function onDeviceReady()
{
    // note, it takes a few seconds for the gps to work, so you need to give a high timeout value
    let options = {maximumAge: 1000, timeout: 50000, enableHighAccuracy: true};
    navigator.geolocation.getCurrentPosition(onGeolocationSuccess, onGeolocationError, options);
}


function onGeolocationSuccess(position)
{
    // Make the map type button visible, so that the user can change the map type	
    document.getElementById('mapType').style.visibility = 'visible';

    let latitude = position.coords.latitude;
    let longitude = position.coords.longitude;

    let mapOptions = {zoom: 15,
        center: new google.maps.LatLng(latitude, longitude),
        mapTypeId: google.maps.MapTypeId.ROADMAP};
    currentLocationMap = new google.maps.Map(document.getElementById('geolocationDetails'), mapOptions);

    let currentLocation = ['You are here!', latitude, longitude, 1];
    let locationMarker;
    let mapWindow = new google.maps.InfoWindow();

    locationMarker = new google.maps.Marker({position: new google.maps.LatLng(currentLocation[1], currentLocation[2]), map: currentLocationMap});

    let locationMarkerNumber = 0;
    google.maps.event.addListener(locationMarker,
            'click',
            (function (locationMarker, locationMarkerNumber) {
        return function ()
                {
        mapWindow.setContent(currentLocation[0]);
                    mapWindow.open(currentLocationMap, locationMarker);
        }
            })(locationMarker, locationMarkerNumber));

}


function onGeolocationError(error)
{
    document.getElementById('geolocationDetails').innerHTML = 'code: ' + error.code + '<br>' +
            'message: ' + error.message + '<br>';
}


function toggleMapType()
{
    if (document.getElementById('mapType').innerHTML == 'Change Map To Hybrid')
    {
        currentLocationMap.setMapTypeId(google.maps.MapTypeId.HYBRID);
        document.getElementById('mapType').innerHTML = 'Change Map To Road';
    }
    else
    {
        currentLocationMap.setMapTypeId(google.maps.MapTypeId.ROADMAP);
        document.getElementById('mapType').innerHTML = 'Change Map To Hybrid'
    }
}
</script>
</head>

<body>
<div id="geolocationDetails">
<h3>Current Location Map Demo</h3>
<p>loading...</p><p>It can take several seconds for the map to load. Please be patient.</p>
</div>
<button id = 'mapType' onclick = 'toggleMapType()'>Change Map To Hybrid</button>
</body>
</html>

Localised Route Planner

Click here to download a .zip containing an example app that shows a GoogleMap route planner that allows the user to start a route from the current position (this app is called e122).

config.xml

<widget  xmlns="http://cordova.apache.org/ns/1.0"
version="1.0.0"
id="ie.dkit.derek_e122" > <name>e122</name> <description>Demo with Route Finder</description> <author email="derek.oreilly@dkit.ie" href="http://derek.dkit.ie">Derek O Reilly</author> <platform name="ios"> <icon src="res/icons/ios/icon-1024.png" width="1024" height="1024"/> <icon src="res/icons/ios/icon-small.png" width="29" height="29"/> <icon src="res/icons/ios/icon-small@2x.png" width="58" height="58"/> <icon src="res/icons/ios/icon-small@3x.png" width="87" height="87"/> <icon src="res/icons/ios/icon-small-40.png" width="40" height="40"/> <icon src="res/icons/ios/icon-small-40@2x.png" width="80" height="80"/> <icon src="res/icons/ios/icon-small-40@3x.png" width="120" height="120"/> <icon src="res/icons/ios/icon-small-50.png" width="50" height="50"/> <icon src="res/icons/ios/icon-small-50@2x.png" width="100" height="100"/> <icon src="res/icons/ios/icon.png" width="57" height="57"/> <icon src="res/icons/ios/icon@2x.png" width="114" height="114"/> <icon src="res/icons/ios/icon-60.png" width="60" height="60"/> <icon src="res/icons/ios/icon-60@2x.png" width="120" height="120"/> <icon src="res/icons/ios/icon-60@3x.png" width="180" height="180"/> <icon src="res/icons/ios/icon-72.png" width="72" height="72"/> <icon src="res/icons/ios/icon-72@2x.png" width="144" height="144"/> <icon src="res/icons/ios/icon-76.png" width="76" height="76"/> <icon src="res/icons/ios/icon-76@2x.png" width="152" height="152"/> <icon src="res/icons/ios/icon-167.png" width="167" height="167"/> <icon src="res/icons/ios/icon-83.5@2x.png" width="167" height="167"/> <splash src="res/screens/ios/Default~iphone.png" width="320" height="480"/> <splash src="res/screens/ios/Default@2x~iphone.png" width="640" height="960"/> <splash src="res/screens/ios/Default-Portrait~ipad.png" width="768" height="1024"/> <splash src="res/screens/ios/Default-Portrait@2x~ipad.png" width="1536" height="2048"/> <splash src="res/screens/ios/Default-568h@2x~iphone.png" width="640" height="1136"/> <splash src="res/screens/ios/Default-667h.png" width="750" height="1334"/> <splash src="res/screens/ios/Default-736h.png" width="1242" height="2208"/> </platform> <platform name="android"> <icon density="ldpi" src="res/icons/android/ldpi.png"/> <icon density="mdpi" src="res/icons/android/mdpi.png"/> <icon density="hdpi" src="res/icons/android/hdpi.png"/> <icon density="xhdpi" src="res/icons/android/xhdpi.png"/> <icon density="xxhdpi" src="res/icons/android/xxhdpi.png"/> <icon density="xxxhdpi" src="res/icons/android/xxxhdpi.png"/> <splash density="port-ldpi" src="res/screens/android/splash-port-ldpi.png"/> <splash density="port-mdpi" src="res/screens/android/splash-port-mdpi.png"/> <splash density="port-hdpi" src="res/screens/android/splash-port-hdpi.png"/> <splash density="port-xhdpi" src="res/screens/android/splash-port-xhdpi.png"/> <splash density="port-xxhdpi" src="res/screens/android/splash-port-xxhdpi.png"/> <splash density="port-xxxhdpi" src="res/screens/android/splash-port-xxxhdpi.png"/> </platform> <platform name="windows"> <icon src="res/icons/windows/storelogo.png" target="StoreLogo" /> <icon src="res/icons/windows/smalllogo.png" target="Square30x30Logo" /> <icon src="res/icons/windows/Square44x44Logo.png" target="Square44x44Logo" /> <icon src="res/icons/windows/Square70x70Logo.png" target="Square70x70Logo" /> <icon src="res/icons/windows/Square71x71Logo.png" target="Square71x71Logo" /> <icon src="res/icons/windows/Square150x150Logo.png" target="Square150x150Logo" /> <icon src="res/icons/windows/Square310x310Logo.png" target="Square310x310Logo" /> <splash src="res/screens/windows/splashscreen.png" target="SplashScreen"/> <splash src="res/screens/windows/splashscreenphone.png" target="SplashScreenPhone"/> </platform> <preference name="DisallowOverscroll" value="true" /> <!-- ios: stop overscroll/bounce --> <preference name="orientation" value="portrait" /> <!-- all: default means both landscape and portrait are enabled --> <preference name="fullscreen" value="true" /> <!-- all: hides the status bar at the top of the screen --> <preference name="exit-on-suspend" value="true" /> <!-- ios: if set to true, app will terminate when home button is pressed --> <config-file platform="ios" parent="UIViewControllerBasedStatusBarAppearance" overwrite="true"> <false/> <!-- true = show status bar, false = hide status bar --> </config-file> <plugin name="cordova-plugin-geolocation" spec="~2.4.3" /> <!-- Allow access various files that relate to the GoogleMaps API --> <access origin="*" /> </widget>

 

index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="initial-scale=1, width=device-width, height=device-height, viewport-fit=cover">
<title>Route Finder Demo</title>
<style>
*
{
    -webkit-touch-callout: none;  /* Disable element selection in app */
    -webkit-user-select: none;    /* Disable text selection in app */ 
}

html, 
body, 
#geolocationDetails 
{
    width:100%;
    height: 100%;
    margin: 0px;
    padding: 0px
}

#controlPanel 
{
    position: absolute;
    top: 10px;
    left: 10px;
    z-index: 2;
    background-color: #fff;
    padding: 5px;
    border: 1px solid #999;
    visibility:hidden;
}

h3,
p
{
    margin:5px;
}
</style>

<!-- This is needed to access the PhoneGap JavaScript -->
<script type="text/javascript" charset="utf-8" src="cordova.js"></script>

<!-- Google Maps -->
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>

<script>
let currentLocationMap;
let directionsDisplay;
let directionsService = new google.maps.DirectionsService();
let currentLocationMap;
let latitude;
let longitude;

window.onload = onAllAssetsLoaded;
document.write("<div id='loadingMessage'>Loading...</div>");
function onAllAssetsLoaded()
{
    // Wait for Cordova to connect with the device
    document.addEventListener("deviceready", onDeviceReady, false);
}

// Cordova is ready to be used!
function onDeviceReady()
{
    // note, it takes a few seconds for the gps to work, so you need to give a high timeout value
    let options = {maximumAge: 1000, timeout: 50000, enableHighAccuracy: true};
    navigator.geolocation.getCurrentPosition(onGeolocationSuccess, onGeolocationError, options);
}


function onGeolocationSuccess(position)
{
    latitude = position.coords.latitude;
    longitude = position.coords.longitude;

    // set the value for the Current Location selection  
    document.getElementById('currentLocationOption').value = latitude.toString() + "," + longitude.toString();

    // Show the controlPanel
    document.getElementById('controlPanel').style.visibility = 'visible';

    // route planner
    directionsDisplay = new google.maps.DirectionsRenderer();
    let currentLocationMap = new google.maps.LatLng(latitude, longitude);
    let mapOptions = {zoom: 10, center: currentLocationMap};
    currentLocationMap = new google.maps.Map(document.getElementById('geolocationDetails'), mapOptions);

    // assign the directionsDisplay to the map
    directionsDisplay.setMap(currentLocationMap);

    calculateRoute();  // calculate initial route from current location to DkIT
}


function onGeolocationError(error)
{
    document.getElementById('geolocationDetails').innerHTML = 'code: ' + error.code + '<br>' +
            'message: ' + error.message + '<br>';
}


function calculateRoute()
{
    let start = document.getElementById('start').value;
    let end = document.getElementById('end').value;

    let request = {origin: start,
        destination: end,
        travelMode: google.maps.TravelMode.DRIVING};

    directionsService.route(request, function (response, status)
    {
if (status == google.maps.DirectionsStatus.OK)
        {
            directionsDisplay.setDirections(response);
        }
});
}
</script>
</head>

<body>
<div id="controlPanel">
<b>Start: </b>
<select id="start" onchange="calculateRoute();">
<option id = 'currentLocationOption'>Current Location</option> <!-- Current Locaiton value can only be set after the location is known -->
<option value="Dundalk Institute of Technology Louth Ireland">DkIT</option>
<option value="Dublin City University Collins Avenue Extension Whitehall Dublin 9">DCU</option>
<option value="Maynooth University Ireland">Maynooth</option>
</select>

<br><b>End: </b>
<select id="end" onchange="calculateRoute();">
<option value="Dundalk Institute of Technology Louth Ireland">DkIT</option>
<option value="Dublin City University Collins Avenue Extension Whitehall Dublin 9">DCU</option>
<option value="Maynooth University Ireland">Maynooth</option>
</select>
</div>

<div id="geolocationDetails">
<h3>Route Finder Demo</h3>
<p>loading...</p><p>It can take several seconds for the map to load. Please be patient.</p>
</div>           
</body>
</html>

Adjust the above code to include the route's text directions, as shown here (this app is called e123).

Compass Core Plugin

The compass plugin retrieves the magnetic bearinctx. In order to use the compas plugin, you need to include the code below in the config.xml

<gap:plugin name="orctx.apache.cordova.device-orientation" />

Click here to download a .zip containing an example app that displays the magnetic heading on an enabled device (this app is called e124).

confix.xml

<widget  xmlns="http://cordova.apache.org/ns/1.0"
version="1.0.0"
id="ie.dkit.derek_e124" > <name>e124</name> <description>Demo showing a phones compass mangetic heading</description> <author email="derek.oreilly@dkit.ie" href="http://derek.dkit.ie">Derek O Reilly</author> <platform name="ios"> <icon src="res/icons/ios/icon-1024.png" width="1024" height="1024"/> <icon src="res/icons/ios/icon-small.png" width="29" height="29"/> <icon src="res/icons/ios/icon-small@2x.png" width="58" height="58"/> <icon src="res/icons/ios/icon-small@3x.png" width="87" height="87"/> <icon src="res/icons/ios/icon-small-40.png" width="40" height="40"/> <icon src="res/icons/ios/icon-small-40@2x.png" width="80" height="80"/> <icon src="res/icons/ios/icon-small-40@3x.png" width="120" height="120"/> <icon src="res/icons/ios/icon-small-50.png" width="50" height="50"/> <icon src="res/icons/ios/icon-small-50@2x.png" width="100" height="100"/> <icon src="res/icons/ios/icon.png" width="57" height="57"/> <icon src="res/icons/ios/icon@2x.png" width="114" height="114"/> <icon src="res/icons/ios/icon-60.png" width="60" height="60"/> <icon src="res/icons/ios/icon-60@2x.png" width="120" height="120"/> <icon src="res/icons/ios/icon-60@3x.png" width="180" height="180"/> <icon src="res/icons/ios/icon-72.png" width="72" height="72"/> <icon src="res/icons/ios/icon-72@2x.png" width="144" height="144"/> <icon src="res/icons/ios/icon-76.png" width="76" height="76"/> <icon src="res/icons/ios/icon-76@2x.png" width="152" height="152"/> <icon src="res/icons/ios/icon-167.png" width="167" height="167"/> <icon src="res/icons/ios/icon-83.5@2x.png" width="167" height="167"/> <splash src="res/screens/ios/Default~iphone.png" width="320" height="480"/> <splash src="res/screens/ios/Default@2x~iphone.png" width="640" height="960"/> <splash src="res/screens/ios/Default-Portrait~ipad.png" width="768" height="1024"/> <splash src="res/screens/ios/Default-Portrait@2x~ipad.png" width="1536" height="2048"/> <splash src="res/screens/ios/Default-568h@2x~iphone.png" width="640" height="1136"/> <splash src="res/screens/ios/Default-667h.png" width="750" height="1334"/> <splash src="res/screens/ios/Default-736h.png" width="1242" height="2208"/> </platform> <platform name="android"> <icon density="ldpi" src="res/icons/android/ldpi.png"/> <icon density="mdpi" src="res/icons/android/mdpi.png"/> <icon density="hdpi" src="res/icons/android/hdpi.png"/> <icon density="xhdpi" src="res/icons/android/xhdpi.png"/> <icon density="xxhdpi" src="res/icons/android/xxhdpi.png"/> <icon density="xxxhdpi" src="res/icons/android/xxxhdpi.png"/> <splash density="port-ldpi" src="res/screens/android/splash-port-ldpi.png"/> <splash density="port-mdpi" src="res/screens/android/splash-port-mdpi.png"/> <splash density="port-hdpi" src="res/screens/android/splash-port-hdpi.png"/> <splash density="port-xhdpi" src="res/screens/android/splash-port-xhdpi.png"/> <splash density="port-xxhdpi" src="res/screens/android/splash-port-xxhdpi.png"/> <splash density="port-xxxhdpi" src="res/screens/android/splash-port-xxxhdpi.png"/> </platform> <platform name="windows"> <icon src="res/icons/windows/storelogo.png" target="StoreLogo" /> <icon src="res/icons/windows/smalllogo.png" target="Square30x30Logo" /> <icon src="res/icons/windows/Square44x44Logo.png" target="Square44x44Logo" /> <icon src="res/icons/windows/Square70x70Logo.png" target="Square70x70Logo" /> <icon src="res/icons/windows/Square71x71Logo.png" target="Square71x71Logo" /> <icon src="res/icons/windows/Square150x150Logo.png" target="Square150x150Logo" /> <icon src="res/icons/windows/Square310x310Logo.png" target="Square310x310Logo" /> <splash src="res/screens/windows/splashscreen.png" target="SplashScreen"/> <splash src="res/screens/windows/splashscreenphone.png" target="SplashScreenPhone"/> </platform> <preference name="DisallowOverscroll" value="true" /> <!-- ios: stop overscroll/bounce --> <preference name="orientation" value="portrait" /> <!-- all: default means both landscape and portrait are enabled --> <preference name="fullscreen" value="true" /> <!-- all: hides the status bar at the top of the screen --> <preference name="exit-on-suspend" value="true" /> <!-- ios: if set to true, app will terminate when home button is pressed --> <config-file platform="ios" parent="UIViewControllerBasedStatusBarAppearance" overwrite="true"> <false/> <!-- true = show status bar, false = hide status bar --> </config-file> <!-- Compass --> <plugin name="cordova-plugin-device-orientation" /> </widget>

index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="initial-scale=1, width=device-width, height=device-height, viewport-fit=cover">
<!-- This is needed to access the PhoneGap JavaScript -->
<script type="text/javascript" charset="utf-8" src="cordova.js"></script>

<title>Worked example from lecture notes</title>
<style>
*{
    -webkit-touch-callout: none;
    -webkit-user-select: none; /* Disable selection/copy in UIWebView */
}

body
{
    padding:0px;
    margin:0px;
}

p
{
    margin-left:5px;
}

#loadingMessage
{
    position:fixed;
    top:100px;
    left:100px;
    z-index:100;
    font-size:50px;
}
</style>
<script>
let compassWatchID = null;

window.onload = onAllAssetsLoaded;
document.write("<div id='loadingMessage'>Loading...</div>");
function onAllAssetsLoaded()
{
    // Wait for Cordova to connect with the device
    document.addEventListener("deviceready", onDeviceReady, false);
}

// Cordova is ready to be used!
function onDeviceReady()
{
    // hide the webpage loading message
    document.getElementById('loadingMessage').style.visibility = "hidden";

    startCompassWatch();
}


function startCompassWatch()
{
    // Update compass every 1 second
    let options = {frequency: 100};

    compassWatchID = navigator.compass.watchHeading(getCompassHeading, onError, options);
}


function getCompassHeading(heading)
{
    document.getElementById('compass').innerHTML = "<p>Magnetic Heading: " + heading.magneticHeading + "</p>";
}


function onError(compassError)
{
    alert('Compass error: ' + compassError.code);
}
</script>
</head>
<body>
<div id = "compass">
<p>Getting magnetic heading</p>
</div>
</body>
</html>

Write code to display a compass, as shown here (this app is called e125).

Write code to overlay a compass on a map of the current location, as shown here (this app is called e126).

WatchPosition

The GoogleMaps API WatchPosition() function can be used to continuously keep track of the current GPS position. The is useful in apps that involve the user moving around. The example below will display the path on a map of the route that a user has taken.

Click here to download a .zip containing an example app that will display the path on a map of the route that a user has taken (this app is called e127).

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="initial-scale=1, width=device-width, height=device-height, viewport-fit=cover">
        <title>Worked example from lecture notes</title>
        <style>
            *{
                -webkit-touch-callout: none;
                -webkit-user-select: none; /* Disable selection/copy in UIWebView */
            }

            html, 
            body
            {
                width:100%;
                height: 100%;
                margin: 0px;
                padding: 0px;
            }

            #walkDetailsDiv 
            {
                width:100%;
                height: 5%;
                min-height:3em;
                margin: 0px;
                padding: 0px;
                background-color: #fff;
                padding: 5px;
                visibility:hidden;
            }

            #routeDiv 
            {
                width:100%;
                height: 75%;
                margin: 0px;
                padding: 0px;
            }

            h3,
            p
            {
                margin:5px;
            }


            input[type="button"] 
            {
                padding:0.2em;
                margin:0.2em;
                font-size:larger; 
            }

            #startStopButton
            {
                background-color: #0f0;
            }
        </style>


        <!-- This is needed to access the PhoneGap JavaScript -->
        <script type="text/javascript" charset="utf-8" src="cordova.js"></script>

        <!-- Google Maps -->
        <script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>

        <script>
            let routeMap;
            let directionsDisplay;
            let directionsService = new google.maps.DirectionsService();
            let routeMap;
            let latitude = 0.0;
            let longitude = 0.0;
            let latitudeAndLongitude;
            let poly = null;
            let marker = null;
            let id = null;
            let routeMap = null;
            let mapZoom = 16;
            let textOutputInterval = null;
            let distanceInMeters = 0;
            let options = {maximumAge: 1000, timeout: 50000, enableHighAccuracy: true}; // note, it takes a few seconds for the gps to work, so you need to give a high timeout value

            let oldLatitude = null;
            let oldLongitude = null;
            let path = null;

            document.addEventListener("deviceready", onDeviceReady, false);
            function onDeviceReady()
            {
                document.getElementById('walkDetailsDiv').style.visibility = 'visible'; // Show the walkDetailsDiv

                navigator.geolocation.getCurrentPosition(onGetCurrentPositionSuccess, onGeolocationError, options);
            }

            function onGetCurrentPositionSuccess(position)
            {
                latitude = position.coords.latitude;
                longitude = position.coords.longitude;
                initialiseMapPosition(latitude, longitude);
            }

            function initialiseMapPosition(latitude, longitude)
            {

                directionsDisplay = new google.maps.DirectionsRenderer();

                latitudeAndLongitude = new google.maps.LatLng(latitude, longitude);

                let mapOptions = {zoom: mapZoom, center: routeMap, mapTypeId: google.maps.MapTypeId.ROADMAP};
                routeMap = new google.maps.Map(document.getElementById('routeDiv'), mapOptions);

                // assign the directionsDisplay to the map
                directionsDisplay.setMap(routeMap);

                poly = new google.maps.Polyline({
                    strokeColor: '#f00',
                    strokeOpacity: 0.5,
                    strokeWeight: 7
                });
                poly.setMap(routeMap);
            }

            function onGeolocationSuccess(position)
            {
                // set latitude and longitude global variables
                latitude = position.coords.latitude;
                longitude = position.coords.longitude;
                if (oldLatitude === null)
                {
                    oldLatitude = latitude;
                    oldLongitude = longitude;

                    marker = new google.maps.Marker({
                        position: latitudeAndLongitude,
                        map: routeMap,
                        title: "You are here."
                    });
                }
                
                latitudeAndLongitude = new google.maps.LatLng(latitude, longitude);
                path = poly.getPath();
                path.push(latitudeAndLongitude);
                
                distanceInMeters = google.maps.geometry.spherical.computeLength(path);

                // recentre map around current location
                routeMap.setCenter(new google.maps.LatLng(latitude, longitude));
                marker.setPosition(new google.maps.LatLng(latitude, longitude));

                oldLatitude = latitude;
                oldLongitude = longitude;
            }

            function displayTextOutput()
            {
                details = "Distance walked: " + distanceInMeters.toFixed(0);
                document.getElementById("walkDetailsDiv").innerHTML = details;
            }

            function onGeolocationError(error)
            {
                document.getElementById("walkDetailsDiv").innerHTML = "Error: " + details;
            }

            function startStop()
            {
                clearInterval(textOutputInterval);
                if (document.getElementById('startStopButton').value === 'Start')
                {
                    document.getElementById('startStopButton').value = 'Stop';
                    document.getElementById('startStopButton').style.backgroundColor = '#f00';

                    initialiseMapPosition(latitude, longitude);

                    // start the route
                    marker = null;
                    oldLatitude = null;
                    oldLongitude = null;
                    path = null;

                    window.plugins.insomnia.keepAwake();

                    let options = {'enableHighAccuracy': true, 'timeout': 10000, 'maximumAge': 20000};
                    id = navigator.geolocation.watchPosition(onGeolocationSuccess, onGeolocationError, options);

                    textOutputInterval = setInterval(displayTextOutput, 1000); // update the text output every second
                }
                else
                {
                    document.getElementById('startStopButton').value = 'Start';
                    document.getElementById('startStopButton').style.backgroundColor = '#0f0';

                    // stop tracking the route
                    window.plugins.insomnia.allowSleepAgain();
                    navigator.geolocation.clearWatch(id);
                }
            }
        </script>
    </head>

    <body>
        <div id="controlPanelDiv">
            <input id="startStopButton" type="button" value="Start" onclick="startStop()">
        </div>

        <div id="walkDetailsDiv"></div>

        <div id="routeDiv">
            <h3>Route Finder Demo</h3>
            <p>loading...</p><p>It can take several seconds for the map to load. Please be patient.</p>
        </div>   
    </body>
</html>
 
<div align="center"><a href="../versionC/index.html" title="DKIT Lecture notes homepage for Derek O&#39; Reilly, Dundalk Institute of Technology (DKIT), Dundalk, County Louth, Ireland. Copyright Derek O&#39; Reilly, DKIT." target="_parent" style='font-size:0;color:white;background-color:white'>&nbsp;</a></div>