Location Services with HTML5 GeoLocation

INTRO

AI2 provides a Location Sensor and Location services through the Map component natively, but there is another way, using the HTML5 GeoLocation API through a Webviewer. I aim to show you the basic setup of an aia project to run this, and a few examples of what you might do with it.

The API appears to use a "fused" approach to Google's Location Services, that is, a combination of IP, Data, and GPS, depending on what is available and what is most accurate. I found if I use this on an fixed computer, the locator will return my location as being somewhere near the local exchange, whilst using a smartphone reports an accurate reading of my position. I have found that using the HTML5 Geolocation can return a reliable and accurate method of determining your position, whether you are inside (a building) or outside, or away from wifi/data.

You can return the following values from a location fetch request:

Property:coords.latitude

Returns:The latitude as a decimal number (always returned)

Property:coords.longitude

Returns:The longitude as a decimal number (always returned)

Property:coords.accuracy

Returns:The accuracy of position (always returned)

Property:coords.altitude

Returns:The altitude in meters above the mean sea level (returned if available)

Property:coords.altitudeAccuracy

Returns:The altitude accuracy of position (returned if available)

Property:coords.heading

Returns:The heading as degrees clockwise from North (returned if available)

Property:coords.speed

Returns:The speed in meters per second (returned if available)

Property:timestamp

Returns:The date/time of the response (returned if available)

SETUP

The following will ensure that HMTL5 GeoLocation works during development in companion, and once your app is compiled.

3. You will then need a Button and a Webviewer, along with a WebViewStringChange event block and a label, to return lat/lon/other values back to your app from the webviewer , and another Button in order to "stop" the location finder (more later....)

4. You may also need some form of "stay-awake" routine, to keep your app alive and prevent it from going into the background, I will cover this later....

5. Finally, you will have observed that you need an html file to open in the webviewer, I will move onto these next.

HTML Files

HTML1

<!DOCTYPE html>

<html>

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

<head>

<title>gl1</title>

</head>

<body>

<p>Get your coordinates...</p>

<p id="geo"></p>

<p id="lat"></p>

<p id="lon"></p>

<script>

var options = {

enableHighAccuracy: true,

timeout: 5000,

maximumAge: 0

};

if (navigator.geolocation) {

navigator.geolocation.getCurrentPosition(showPosition, error, options);

} else { 

document.getElementById("geo").innerHTML("Geolocation is not supported by this browser");

if( window.AppInventor ){

var msg = "Geolocation is not supported by this browser";

window.AppInventor.setWebViewString(msg);

}

};

function showPosition(position) {

document.getElementById("lat").innerHTML = "lat: " + position.coords.latitude; 

document.getElementById("lon").innerHTML = "lon: " + position.coords.longitude;

if( window.AppInventor ){

var msg = "[" + position.coords.latitude + "," + position.coords.longitude + "]"

window.AppInventor.setWebViewString(msg);

}

};

function error(err) {

document.getElementById("geo").innerHTML = 'ERROR(' + err.code + '): ' + err.message;

};

</script>

</body>

</html>

HTML2

<!DOCTYPE html>

<html>

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

<head>

<title>gl2</title>

</head>

<body>

<p>Get your coordinates...</p>

<p id="geo"></p>

<p id="lat"></p>

<p id="lon"></p>

<script>

var options = {

enableHighAccuracy: true,

timeout: 5000,

maximumAge: 0

};

if (navigator.geolocation) {

navigator.geolocation.getCurrentPosition(showPosition, error, options);

} else { 

document.getElementById("geo").innerHTML("Geolocation is not supported by this browser");

if( window.AppInventor ){

           var msg = "Geolocation is not supported by this browser";

window.AppInventor.setWebViewString(msg);

}

};

function showPosition(position) {

document.getElementById("lat").innerHTML = "lat: " + position.coords.latitude; 

document.getElementById("lon").innerHTML = "lon: " + position.coords.longitude;

const date = new Date(position.timestamp);

document.getElementById("geo").innerHTML = "timestamp: " + position.timestamp + "<br><br>date: " + date.toString();

if( window.AppInventor ){

var msg = "[" + position.coords.latitude + "," + position.coords.longitude + "," + position.timestamp + "]";

window.AppInventor.setWebViewString(msg);

}

};

function error(err) {

document.getElementById("geo").innerHTML = 'ERROR(' + err.code + '): ' + err.message;

};

</script>

</body>

</html>

HTML3

<!DOCTYPE html>

<html>

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

<head>

<title>gl3</title>

</head>

<body>

<p>Get your coordinates...</p>

<p id="geo"></p>

<p id="lat"></p>

<p id="lon"></p>

<script>

var options = {

enableHighAccuracy: true,

timeout: 5000,

maximumAge: 0

};

if (navigator.geolocation) {

    navigator.geolocation.watchPosition(showPosition, error, options);

} else {

document.getElementById("geo").innerHTML("Geolocation is not supported by this browser");

if( window.AppInventor ){

var msg = "Geolocation is not supported by this browser";

window.AppInventor.setWebViewString(msg);

}

}

function showPosition(position) {

document.getElementById("lat").innerHTML = "lat: " + position.coords.latitude; 

document.getElementById("lon").innerHTML = "lon: " + position.coords.longitude;

const date = new Date(position.timestamp);

document.getElementById("geo").innerHTML = "timestamp: " + position.timestamp + "<br><br>date: " + date.toString();

if( window.AppInventor ){

var msg = "[" + position.coords.latitude + "," + position.coords.longitude + "," + position.timestamp + "]";

window.AppInventor.setWebViewString(msg);

}

};

function error(err) {

document.getElementById("geo").innerHTML = 'ERROR(' + err.code + '): ' + err.message;

};

</script>

</body>

</html>

HTML4

<!DOCTYPE html>

<html>

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

<head>

<title>gl4</title>

</head>

<body>

<p>Get your coordinates...</p>

<p id="geo"></p>

<p id="lat"></p>

<p id="lon"></p>

<script>

var id, target, options;

function success(position) {

if (target.latitude === position.coords.latitude && target.longitude === position.coords.longitude) {

document.getElementById("geo").innerHTML = 'Congratulation, you reach the target';

navigator.geolocation.clearWatch(id);

} else {

document.getElementById("lat").innerHTML = "lat: " + position.coords.latitude; 

document.getElementById("lon").innerHTML = "lon: " + position.coords.longitude;

const date = new Date(position.timestamp);

document.getElementById("geo").innerHTML = "timestamp: " + position.timestamp + "<br><br>date: " + date.toString();

if( window.AppInventor ){

var msg = "[" + position.coords.latitude + "," + position.coords.longitude + "," + position.timestamp + "]";

window.AppInventor.setWebViewString(msg);

}

}

};

function error(err) {

document.getElementById("geo").innerHTML = 'ERROR(' + err.code + '): ' + err.message;

};

target = {

latitude : -90.000,

longitude: 45.000,

}

options = {

enableHighAccuracy: true,

timeout: 5000,

maximumAge: 0

};

id = navigator.geolocation.watchPosition(success, error, options);

</script>

</body>

</html>

Stay-Awake

For examples HTML3 & HTML4, you may want your device/app to remain turned on and awake to continue receiving updates of position long after you phone/device would normally go to sleep. I have employed a simple stayawake routine, using a clock timer set to 10023ms (just over 10 seconds), and a notifier alert that displays "nothing". On my device, the phone settings significantly dim the screen after a time, but the app remains in the foreground.

Clock Timer Settings

Notifier Settings

Block Settings

EXAMPLE

I used the HTML3 file to help me plot a local walk, which was just under 2 miles. Here is the resultant map plotted from the coordinates recorded. I took a reading every 15 seconds (or so):

VIDEO

Showing the four html files in action returning lat/lon/timestamp information. Please note, the lat/lon values are fictitious.

RESOURCES

simpleGeoLocationV2.aia


Credits:

To SteveJG on the AI2 community, for advice, testing and code snippets that helped me to get this all working