Retrieving a location

When you have chosen a positioning method that suits your app, you can request the location (or fix) of a device in your app. When you have found a fix, you can use the QGeoPositionInfo class to extract location information. There are two ways that you can request location information:

Retrieving a single fix

If your app needs a single location fix at a certain point in time, you can just request a single fix. For example, if your social networking app is updating a status with the user's current location, you can request a single fix. Here's how to get a single fix for a device in your app:

//Set up the position info source.
QGeoPositionInfoSource *src = 
    QGeoPositionInfoSource::createDefaultSource(this);

// Connect the positionUpdated() signal to a 
// slot that handles position updates.

bool positionUpdatedConnected = connect(src, 
    SIGNAL(positionUpdated(const QGeoPositionInfo &)), 
    this, 
    SLOT(positionUpdated(const QGeoPositionInfo &)));

if (positionUpdatedConnected) {
    // Signal was successfully connected.
    // Request a single fix and wait for the
    // positionUpdated() signal to be emitted.
    src->requestUpdate();
} else {
    // Failed to connect to signal.
    // This is not normal in most cases and can be
    // a critical situation for your app! Make sure
    // you know exactly why this has happened. Add 
    // some code to recover from the lost connection 
    // below this line.
}

Specifying a timeout period

You can specify a time limit to retrieve the location of a device. If the location isn't found within the specified timeout period, the updateTimeout() signal is emitted. If you requested a single fix, using requestUpdate(120000), the updateTimeout() signal is emitted when the location can't be found within the timeout period (in this case, 2 minutes or 120 seconds). To use the timeout, you must connect a slot that handles the timeout to the updateTimeout() signal. Here's a code sample:

//Set up the position info source.
QGeoPositionInfoSource *src = 
    QGeoPositionInfoSource::createDefaultSource(this);

// Connect the positionUpdated() signal to a 
// slot that handles position updates.
 
bool positionUpdatedConnected = connect(src, 
    SIGNAL(positionUpdated(const QGeoPositionInfo &)), 
    this, 
    SLOT(positionUpdated(const QGeoPositionInfo &)));

if (positionUpdatedConnected) {
    // positionUpdated() SIGNAL connected.

    // Get the position of the device
    src->requestUpdate(120000);
} else {
    // positionUpdated() SIGNAL failed to connect.
    // This is not normal in most cases and can be
    // a critical situation for your app! Make sure
    // you know exactly why this has happened. Add 
    // some code to recover from the lost connection 
    // below this line.}

// Connect the updateTimeout() signal to a 
// slot that handles timeouts.

bool updateTimeoutConnected = connect(src, 
    SIGNAL(updateTimeout()), 
    this, 
    SLOT(positionUpdateTimeout()));

if (updateTimeoutConnected) {
    // updateTimeout() SIGNAL connected.
} else {
    // updateTimeout() SIGNAL failed to connect.
    // This is not normal in most cases and can be
    // a critical situation for your app! Make sure
    // you know exactly why this has happened. Add 
    // some code to recover from the lost connection 
    // below this line.}

You need a slot to handle the positionUpdated() and positionTimeout() signals. Here's how you can define this in your .hpp and .cpp files:

void MyPositionEngine::positionUpdated 
(const QGeoPositionInfo & pos)   
{         
    // Use the position information to update your UI.   
}       

void MyPositionEngine::positionUpdateTimeout()   
{         
    // A timeout occurred, no position update available.   
}   

Retrieving the last known location

The last known location is a special case of a single fix. The last known location of a device can be found using the lastKnownPosition() function. You can restrict this to only retrieve the last known location received from a satellite positioning method by setting fromSatellitePositioningMethodsOnly to true. This returns the last location fix received by any location-based app on the device. This could be the location fix found by another app running location services, not necessarily your app. The lastKnownPosition() function returns the value immediately.

QGeoPositionInfo lastPosition = src->lastKnownPosition(true);   
  

Retrieving multiple fixes

If your app needs to get continuous or multiple location fixes at certain intervals, you can get fixes at regular intervals by using startUpdates(). Every time a location fix is found, the positionUpdated() signal is emitted. Here's how you can do this:

//Set up the position info source.
QGeoPositionInfoSource *src = 
    QGeoPositionInfoSource::createDefaultSource(this);

// Connect the updateTimeout() signal to a 
// slot that handles timeouts.

bool updateTimeoutConnected = connect(src, 
    SIGNAL(updateTimeout()), 
    this, 
    SLOT(positionUpdateTimeout()));

if (updateTimeoutConnected) {
    // updateTimeout() SIGNAL connected.
} else {
    // updateTimeout() SIGNAL failed to connect.
    // This is not normal in most cases and can be
    // a critical situation for your app! Make sure
    // you know exactly why this has happened. Add 
    // some code to recover from the lost connection 
    // below this line.
}

// Connect the positionUpdated() signal to a 
// slot that handles position updates.
 
bool positionUpdatedConnected = connect(src, 
    SIGNAL(positionUpdated(const QGeoPositionInfo &)), 
    this, 
    SLOT(positionUpdated(const QGeoPositionInfo &)));

if (positionUpdatedConnected) {
    // Signal and slot connected.

    // Start receiving updates to the position of the device.
    src->startUpdates();
} else {
    // Failed to connect signal.
    // This is not normal in most cases and can be
    // a critical situation for your app! Make sure
    // you know exactly why this has happened. Add 
    // some code to recover from the lost connection 
    // below this line.
}

You need a slot to handle the positionUpdated() and positionTimeout() signals. Here's an example of something that you could define in your .hpp and .cpp files:

void MyPositionEngine::positionUpdated 
(const QGeoPositionInfo & pos)   
{         
    // Use the position information to update your UI.   
}       

void MyPositionEngine::positionUpdateTimeout()   
{         
    // A timeout occurred, no position update available.   
}   

Specifying intervals for multiple fixes

In most cases, you need to set an interval between requests to find the location of a device. The interval is set in milliseconds using the setUpdateInterval() function. For example, the following code sample specifies that location fixes should be provided every second.

// Emit updates every second if available
QGeoPositionInfoSource *src = 
    QGeoPositionInfoSource::createDefaultSource(this);

if (src)    
    src->setUpdateInterval(1000); 

If you don't specify an interval, updates are provided every 5 seconds.

You can change the interval between updates in your app at any time using setUpdateInterval(). You don't need to stop requesting updates to change the interval between updates.

Starting and stopping updates

You can start and stop regular updates using startUpdates() and stopUpdates().

src->startUpdates();

When startUpdates() is called, each update will be delivered using a positionUpdated() signal.

When your application no longer requires location fixes, you should stop any active position source by calling stopUpdates().
src->stopUpdates();

Getting updates in the background

If you want your app to continue to get location fixes while your app is in the background or minimized, you must set the canRunInBackground property to true. For example, this could be used by a fleet tracking application that needs to update the dispatch office with the current location of the vehicle while the app is minimized.

src->setProperty(“canRunInBackground", true);

Handling errors with updateTimeout()

The updateTimeout() signal is emitted when the positioning source determines that it's temporarily unable to provide a fix. It continues to try to find a position, so your code doesn't need to handle retrying to find a location fix. However, your app can give the user a hint that positioning is temporarily unavailable. For example, a navigational app could give the user a "Lost satellite signal" alert or toast when it receives an updateTimeout() signal.

Your app will only get one updateTimeout() signal to indicate that it can't provide a location fix at this time. Any subsequent errors from an implicit retry won't be reported to the app.

Eventually, your app will get a positionUpdated() signal, and it will reset the timer to 0 and send another updateTimeout() signal if it determines that it can't get a location update within the timeout period.

If you want to specify an absolute timeout period for the first fix, you can use:

src->setProperty("responseTime", "15000");

This forces the location manager to return the first fix within 15 seconds. All subsequent fixes are returned at intervals defined by setUpdateInterval().

Last modified: 2013-12-21

comments powered by Disqus