How do I get the Location and use the Digital Compass?
This lesson describes how to detect the location, heading, acceleration and rotation of a mobile device, using the built in GPS, accelerometer and digital compass hardware. GPS hardware is required for location support, an accelerometer is required for acceleration support and a digital compass is required for heading and rotation support. Screen captures and source code are provided.
Introduction
The iOS and Android engine can track the location, heading, acceleration and rotation of a device, if GPS, accelerometer and digital compass hardware are available. LiveCode commands can start, stop and capture relevant position and heading information that can then be used in your application.
From time to time, an iOS device may request to calibrate the compass hardware. LiveCode provides a feature to set the timeout for the calibration request or probe the current timeout value.
Note: This lesson assumes that your device has GPS, accelerometer and digital compass hardware.
Download the sample stack from this url: https://tinyurl.com/yc2uq5mm
A Simple Test Interface
Create a simple application interface, as is show in the figure of this section. The interface consists of eight buttons and a text field. The buttons control the activation of tracking location, heading, acceleration, rotation rate and the timeout settings. The text field displays the location, heading, acceleration, rotation rate and error information from the device.
You can select which sensor you would like to access by selecting the sensor option from the button that displays the label "Location". Selecting this button opens a combo box that provides a selection of sensors that can be accessed.
The stack card contains the following five message handlers that update the text field:
on rotationRateChanged
put the params & return before field "log"
end rotationRateChanged
on locationChanged
put the params & return before field "log"
end locationChanged
on headingChanged
put the params & return before field "log"
end headingChanged
on accelerationChanged
put the params & return before field "log"
end accelerationChanged
on trackingError
put the params & return before field "log"
end trackingError
Testing for Location Tracking Support
Button "Test for Support" tests whether or not the device provides support for the sensor selected by the top right button. The code on the button script is as follows:
on mouseUp
if mobileSensorAvailable (the label of button "sensor") is true then
answer the label of button "sensor" && "Tracking is Supported." with "Okay"
else
answer the label of button "sensor" && "Tracking is not Supported." with "Okay"
end if
end mouseUp
This calls function mobileSensorAvailable()
that returns either true or false. Depending on the name of the sensor type passed in to this function, the result may vary. Not all devices support all sensors that are accessible via LiveCode.
Getting Location Information
Button "Start Tracking" informs LiveCode that the selected sensor should start to collect data. The code of that button is as follows:
on mouseUp
mobileStartTrackingSensor the label of button "sensor", the hilited of button "Loosely"
end mouseUp
Note: mobileStartTrackingSensor
may request permission from the user to access the GPS hardware, depending on how the system preferences have been set up.
If location tracking cannot be started, either because device support is not available or because the user denied access to GPS information then a trackingError message is sent.
In this example, once the location is being tracked, LiveCode sends locationChanged
messages to your stack, each time a change in location is detected.
Sensor tracking can be halted by selecting button "Stop Tracking", which has the following code:
on mouseUp
mobileStopTrackingSensor the label of button "sensor"
end mouseUp
You can request sensor information directly, without having to process the changed messages. This is implemented under button "Get Current Reading" with the following code:
on mouseUp
get mobileSensorReading(the label of button "sensor", true)
if it is an array then
combine it using return and "="
end if
put "Current Reading" && it & return before field "log"
end mouseUp
mobileSensorReading ("location", true)
returns an array with the following information:
- horizontal accuracy – The maximum error in meters of the position indicated by longitude and latitude.
- latitude – The latitude of the current location, measured in degrees relative to the equator. Positive values indicate positions in the Northern Hemisphere, negative values indicate positions in the Southern Hemisphere.
- longitude – The longitude of the current location, measured in degrees relative to the zero meridian. Positive values extend east of the meridian, negative values extend west of the meridian.
- vertical accuracy – The maximum error in meters of the altitude value.
- altitude – The distance in meters of the height of the device relative to sea-level. Positive values extend upward of sea-level, negative values downward.
- timestamp – the time at which the measurement was taken, in seconds since 1970.
Note: If the latitude and longitude could not be measured, then those keys, together with the horizontal accuracy key are not present. If the altitude could not be measured, then that key together with the vertical accuracy are not be present.
Test for Heading Tracking Support
Select "Heading" from the top right button and then press button "Test for Support". This test whether your device supports heading data. Similarly, by selecting acceleration and rotation rate, you can test for the availability of the other sensor types.
Note: Digital compass support is only available in iOS 4.0 and later.
Getting Heading Information
Button "Start Tracking", in conjunction with the selection of "Heading" informs LiveCode that heading information should be collected. The code of that button is as follows:
If heading tracking cannot be started, then the headingError
message is sent.
Once the heading is being tracked, LiveCode sends headingChanged
messages to your stack, each time a change in heading is detected.
Heading tracking can be halted by selecting button "Stop Tracking", that has the following code:
You can request heading information outside of the headingChanged
messages that are sent when heading changes are detected. This is implemented under button "Get Current Reading".
mobileSensorReading ("heading", true)
returns an array with the following information:
- accuracy – The maximum deviation (measured in degrees) between the reported heading and true geomagnetic heading. The lower the value, the more accurate the reading.
- magnetic heading – The heading (measured in degrees) relative to magnetic north.
- true heading – The heading (measured in degrees) relative to true north. If the true heading could not be calculated (usually due to location tracking not being enabled, or lack of calibration), then this key is not present.
- heading – The true heading, if available, otherwise the magnetic heading.
- x, y, z – The geomagnetic data (measured in microtesla) for each of the x, y, and z axes.
- timestamp – the time at which the measurement was taken, in seconds since 1970.
Note: In order to calculate the true heading, location tracking must be enabled simultaneously with heading tracking.
Other Sensor Support
In addition to location and heading, LiveCode also supports acceleration and rotation rate.
The detailed reading for these sensors returns the following information:
mobileSensorReading ("acceleration", true)
returns an array with the following information:
- x, y, z – The acceleration in for each of the x, y, and z axes.
- timestamp – the time at which the measurement was taken, in seconds since 1970.
mobileSensorReading ("rotation rate", true)
returns an array with the following information:
- x, y, z – The change in rotation for each of the x, y, and z axes.
- timestamp – the time at which the measurement was taken, in seconds since 1970.
Setting the Calibration Timeout Value
An iOS device may sometimes prompt the user to calibrate the magnetometer in order to provide reliable heading information. This feature is turned off by default and will not allow the user to be prompted, if a calibration may be required.
A timeout delay in seconds can be set using iphoneSetHeadingCalibrationTimeout
. This allows the device to prompt the user to perform a calibration, should one be needed. If the timeout delay is set to 0, no calibration requests are permitted. Values greater than 0 specify the duration for which the calibration request prompt is displayed. The message is automatically dismissed, if the user does not respond to the message in the time set by the timeout.
The following code allows the user to set the timeout delay:
on mouseUp
ask question "What Timeout do You want?" with "10" titled "Heading Calibration Timeout"
if it is an integer then
iphoneSetHeadingCalibrationTimeout it
end if
end mouseUp
Getting the Calibration Timeout Value
The value of the timeout delay can be returned using iphoneHeadingCalibrationTimeout()
.
on mouseUp
local tResult
put iphoneHeadingCalibrationTimeout() into tResult
if tResult is a number then
answer "Heading Calibration Timeout is set to:" && tResult with "Okay"
else
answer "No Heading Calibration Timeout available." with "Okay"
end if
end mouseUp
Thomas McGrath III
As is the stack included with this lesson does not report heading information. I downloaded and selected my provisioning profile and built the standalone. When I select the "Test for Heading Support" It is confirmed yet no data is collected after selecting the "Start Heading Tracking" and then selecting the "Get Current Heading".
I am able to get the heading to work in other stacks.
LiveCode 5.0.2 (1469)
iPhone4 (not 4S)
xCode 4.2 (4D199)
iOS 5.0.1 (9A405)
Hanson Schmidt-Cornelius
Hi Thomas,
thank you for your comment. An updated version of the stack is now available for download.
Kind Regards,
Hanson
genie
When is "on trackingError" triggered? Is it triggered when device goes out of coverage area such as where GPS cannot be tracked?
Thanks,
Genie
Hanson Schmidt-Cornelius
Hi Genie,
the "trackingError" is not specific to GPS and is also triggered by the acceleration and rotation sensors.
Reasons for a GPS error could be that the sensor has just been started, the user denied use of it or your device could not receive a signal.
Kind Regards,
Hanson
Lungile
If I am able to use GPS navigation on an Android phone, does that not mean mobile tracking is allowed on the phone?
When I test for mobile Sensor to check for support, it gives a not supported message. I'm not sure why because my phone has GPS navigation.
Hanson Schmidt-Cornelius
Hi Lungile,
have you tested if mobile tracking is permitted for the application you created?
Kind Regards,
Hanson
Lungile
Hi Hanson
Yes, everything is working perfectly now. Thank you very much.
Kind regards
Lungile
Jack
Everytime I try to save this as a Standalone Android APK using Windows 7 I get told not supported on this platform
What's wrong?
Hanson Schmidt-Cornelius
Hi Jack,
yes, you would get that message if you are trying to build an iOS standalone from Windows. The reason you were getting that message is because the standalone application settings were set to build for iOS. Unsetting an iOS build target from Windows can be challenging.
I have uploaded a new version of the stack that is set to build for Android by default.
Anyone who is loading the stack on a Mac can set the build target to iOS if they like.
Kind Regards,
Hanson
Andres
I have a Samsung J5 2016 (Android 6) smartphone mobile and have GPS, but this sample says that GPS is not supported on my phone?
Thank you
simon
What's the best way to retrieve just on member of the array returned when getting the sensor with mobileSensorReading ("location", true)?
In other words let say after executing the above command I just want to retrieve the timestamp of the reading. How should I do it?
Thanks
Elanor Buchanan
Hi Simon
As mobileSensorReading ("location", true) returns an array you can access any specific key using array notation e.g.
put mobileSensorReading ("location", true) into tDetails
put tDetails["timestamp"] into tTimestamp
I hope that helps.
Elanor
simon
Thanks Elanor that's perfect. Another great LC feature.
I should have thought about this...
Regards
Simon Schvartzman
Hi Elanor, many thanks for your clarification. I wonder if you have seen any script that would calculate the speed the GPS is traveling (by car) using the GPS data. The one I have developed so far gives me pretty unstable results. I saw a few old posts on the forum regarding the subject but none was conclusive. Regards
Elanor Buchanan
Hi Simon,
The location sensor will actually return a speed component in the correct circumstances, if there is not a measurable speed the key will not be included in the array.
This was added in LiveCode 6.0
https://quality.livecode.com/show_bug.cgi?id=10635
But there is a bug reported against the documentation for mobileSensorReading and mobileCurrentLocation, specifically that this is not documented.
https://quality.livecode.com/show_bug.cgi?id=16662
If that is not helpful I think the best option is to use the Haversine formula, although this will not be very accurate for driving on roads.
I hope that helps.
Kind regards
Elanor