|
||
This document explains how to get location information using the Location Acquisition API.
Location Acquisition API overview describes the main client/server classes of the API.
Position data and info classes describes the classes that hold location information.
Client applications use the RPositionServer
and
RPositioner
classes to get position updates.
RPositionServer
is used by client applications to manage a session
with the location server and to get positioning technology module information.
RPositioner
is used by client applications to manage a subsession
with the location server and to get position updates.
For each location request from a client, the LBS subsystem can operate in one of several different positioning modes. The Location Acquisition API hides the details of which positioning mode is in use from client applications. A client makes the same sequence of calls to the API to get a position update whichever positioning mode is used. Note that only some of these positioning modes may be available to a client application at runtime.
Each positioning mode is a different way of getting a position fix:
Autonomous
LBS uses a GPS positioning module to calculate position fixes without assistance data from the network. This mode typically takes the longest time to obtain a location fix compared to the other modes.
Terminal Based Mode
LBS uses an A-GPS positioning module to calculate position fixes using assistance data from the network. Assistance data specifies the GPS satellites that are above the horizon as seen from the mobile device's current location. Assistance data is used by an A-GPS positioning module to reduce the time necessary to obtain a position fix.
The network can also supply a reference position to the LBS subsystem as part of the sequence of events. This position is calculated in the network using cell-based techniques and may be less accurate than that obtained from GPS. If a reference position is available, it may be returned to the client before a GPS position.
See Location Acquisition API runtime behaviour for more information about the position updates that can be returned by LBS.
Terminal Assisted Mode
LBS uses an A-GPS positioning module to obtain GPS measurements (using assistance data from the network). GPS measurements are the raw data used to calculate a GPS fix. Measurements are sent to the network and a position fix is calculated by a remote server. The remotely calculated position fix is returned to the mobile device and is known as the final network position. The LBS subsystem returns this position to the client.
Simultaneous Terminal Based Mode and Terminal Assisted Mode.
LBS passes GPS measurements to the network (as in Terminal Assisted Mode), but also attempts to use those measurements to calculate a GPS position fix (as in Terminal Based Mode). The position returned to the client may be either a GPS position (calculated in the mobile device) or a final network position (calculated using the measurements by a remote server in the network). The position that is calculated first (the GPS position or the final network position) is generally returned to the client. The final network position may also be returned to the client after the return of the GPS position.
Cell-based Mode
LBS obtains a position fix from the network without using GPS. This position fix is sometimes less accurate than that obtained using GPS.
A client application cannot directly choose the positioning mode that is used for its location request. A handset manufacturer may provide an LBS 'control panel' type of application where the GPS mode can be selected by an end user. However for modes that involve the network (Terminal Based Mode, Terminal Assisted Mode and Cell-based Mode) it is possible for a network operator to override the GPS mode as part of the location request. If a client wants to know precisely how a position fix was calculated, this information is available in the returned position info object (as described in more detail later in this document).
Figure 1 shows a simplified sequence for a client requesting a position update from LBS. The sequence shows simplified behaviour for Terminal Based Mode. The A-GPS Module is a positioning module that uses Assisted GPS to calculate a position. The Network Protocol Module is a positioning module that obtains GPS assistance data and reference positions (often approximate positions) from the network. Note that Terminal Based Mode may not be available on all mobile devices. This depends on the positioning modules that have been installed by the handset manufacturer.
The following code shows a simple example of how a client application can get a single position update. The numbers in the code comments refer to sections that follow the code example.
#include <lbs.h>
#include <lbserrors.h>
...
RPositionServer server;
RPositioner positioner;
// 1. Create a session with the location server
User::LeaveIfError(server.Connect());
CleanupClosePushL(server);
// 2. Create a subsession with the Location Server using default positioning module
User::LeaveIfError(positioner.Open(server));
CleanupClosePushL(positioner);
/* 3 (Optional on platforms other than S60)
This step is only necessary if code is linked to lbs.lib
Set the requester information - in this example define a requester stack... */
_LIT(KCntPhone, "+358501234567");
_LIT(KSrvName, "MyService");
RRequestorStack stack;
CRequestor* contact = CRequestor::NewLC(CRequestor::ERequestorContact, CRequestor::EFormatTelephone, KCntPhone);
stack.Append(contact);
CRequestor* service = CRequestor::NewLC(CRequestor::ERequestorService, CRequestor::EFormatApplication, KSrvName);
stack.Append(service);
User::LeaveIfError(positioner.SetRequestor(stack));
TPositionInfo posInfo;
TPosition pos;
TRequestStatus status;
/* 4. To set update options, call RPositioner::SetUpdateOptions().
See the description in section 4 below */
/* 5. Request location information
Could also call positioner.GetLastKnownPosition(posInfo, status)
to get cached location information */
positioner.NotifyPositionUpdate(posInfo, status);
User::WaitForRequest(status);
// 6. Receive location information
if (status != KErrNone)
{
// Handle possible client/server errors
...
}
// Get the position data object from the wrapper info object
posInfo.GetPosition(pos);
// Use the position data
...
// Reissue the location request if necessary by calling NotifyPositionUpdate() again
/* 7. To cancel or complete a location request a client
calls RPositioner::CancelRequest() or RPositioner::CompleteRequest() */
// 8. Cleanup
stack.Reset();
CleanupStack::PopAndDestroy(service);
CleanupStack::PopAndDestroy(contact);
CleanupStack::PopAndDestroy(&positioner);
CleanupStack::PopAndDestroy(&server);
The following describes the steps to get location information as shown in the above example:
To create a session with the location server, a client application:
Creates an instance of RPositionServer
Standard client-server error codes are returned by calls to open the
session. A panic occurs if the client application has already created a session
with the location server. Error and panic codes specific to LBS are defined in
LbsErrors.h
.
Location information requests are issued on a subsession.
To create a subsession, an application calls one of three overloaded
RPositioner::Open()
member functions:
RPositioner::Open(RPositionServer& aPosServer)
uses the default positioning technology module to get location information. The
client application does not specify any position quality criteria (which
specify the required position accuracy) and therefore LBS uses default position
quality criteria (horizontal accuracy = 50m, vertical accuracy = 1000m, request
timeout = 30 seconds).
RPositioner::Open(RPositionServer& aPosServer,
TPositionModuleId aModuleId)
allows a specific positioning technology
module to be specified by the client application. LBS uses position quality
criteria associated with the specified module. No quality criteria are
specified and so LBS uses the capabilities of the positioning module as the
default criteria.
See Positioning technology modules for information about module position quality and How to use module information for more information about how to get a module ID.
RPositioner::Open(RPositionServer& aPosServer, const
TPositionCriteriaBase& aCriteria)
allows an application to specify a
set of position quality criteria that must be satisfied by LBS. The criteria
specify the capabilities required of the positioning module (such as a
requirement for horizontal and vertical position data) and the accuracy of
position fixes that a client requires.
LBS uses the quality criteria to choose the most appropriate
positioning technology module to use for a client's location requests when the
Open()
method is called. The criteria are also used to specify the
required accuracy of position updates when
RPositioner::NotifyPositionUpdate()
is called.
See Positioning technology module selection criteria for more information about quality criteria.
The LBS subsystem does not compare the vertical accuracy of a calculated position with the vertical accuracy specified by a client application (specified by position quality criteria, by a quality profile or by a positioning module). Only the horizontal accuracy of a calculated position is used to decide if it is accurate enough to be returned to a client application.
If using the Location Acquisition API on the S60 platform it is
necessary to set the client requesters by calling
RPositioner::SetRequestorL()
before calling
RPositioner::NotifyPositionUpdate().
On platforms other than S60, the call is optional (it is not implemented by the Location Server).
For application portability between non-S60 and S60 platforms,
applications must call one of the
RPositioner::SetRequestorL()
methods.
A client application calls
RPositioner::SetUpdateOptions()
to set the update options.
Calling this method only affects future calls to
RPositioner::NotifyPositionUpdate()
and
RPositioner::GetLastKnownPosition()
and does not affect
any outstanding requests.
A TPositionUpdateOptions
parameter specifies the
update options and is passed in RPositioner::SetUpdateOptions()
.
The properties of TPositionUpdateOptions
are set either on its
construction or via setter methods. The following properties can be defined:
The time interval between position updates
TPositionUpdateOptions::SetUpdateInterval(TTimeIntervalMicroSeconds
aInterval)
sets the time interval between position updates.
Setting a non-zero value indicates that the client requires
periodic updates (this is also known as 'tracking'). LBS attempts to send
position updates to the client application with this interval between the
updates. Note that setting aInterval
to 0
(or not
setting it) indicates that the client is not tracking.
Note that when a client application is tracking, LBS does not return reference positions as periodic updates. See the section on Tracking later in this document for more information on tracking behaviour.
A position update timeout
TPositionUpdateOptions::SetUpdateTimeOut(TTimeIntervalMicroSeconds
aTimeOut)
sets a timeout for the location request. It specifies how long
the client application is prepared to wait to obtain a position update. If the
timeout expires RPositioner::NotifyPositionUpdate()
completes and the client's RunL()
method is called.
After a timeout the value set for the client's
TRequestStatus
parameter depends on the configuration of the LBS
subsystem and may be either KErrTimeOut
or
KPositionQualityLoss
. See
Location Acquisition API runtime behaviour for more information.
Note that calling SetUpdateTimeOut()
with a value of 0 (or not setting it) indicates that LBS should not timeout the
location request from a client.
The maximum age of a position update
TPositionUpdateOptions::SetMaxUpdateAge(TTimeIntervalMicroSeconds
aMaxAge)
specifies the maximum age of the position data returned by
RPositioner::NotifyPositionUpdate()
. Setting this value
allows the location server to use cached location information in some cases.
The default value of 0 indicates that new position data is required.
Acceptance of partial updates
A partial update is a position update that contains only partial
position data. Such a position is called an incomplete
position. An example of an incomplete position is one that contains
data about the satellites used to obtain a GPS fix but no latitude or longitude
data. LBS defines an incomplete position to be one where either
TPosition::Latitude()
or TPosition::Longitude()
is
NaN
(Not a Number).
TPositionUpdateOptions::SetAcceptPartialUpdates(TBool
aPartial)
allows an application to choose to accept partial updates. If
a partial update is returned an application's TRequestStatus
parameter is set to KPositionPartialUpdate
when
NotifyPositionUpdate()
completes.
If partial updates are not set the default behaviour is for
RPositioner::NotifyPositionUpdate()
to complete only when
the positioning module used for the location request has obtained as much
information as possible. Note however that this behaviour is configurable by a
Symbian OS licensee (see Location Acquisition API runtime behaviour for more information).
The default constructor of TPositionUpdateOptions
sets all update options to zero by default and is the equivalent of calling the
following:
TPositionUpdateOptions::SetUpdateInterval(0)
meaning
that tracking is off
TPositionUpdateOptions::SetUpdateTimeout(0)
meaning
that LBS should not timeout the client's request
TPositionUpdateOptions::SetMaxUpdateAge(0)
meaning
that new position data is required
TPositionUpdateOptions::SetAcceptPartialUpdates(EFalse)
meaning the partial updates are not returned
When setting update options, a client should beware of causing unexpected side effects. For example, if a client wants to accept partial updates, it might do the following:
Create a new TPositionUpdateOptions
options object
Call
TPositionUpdateOptions::SetAcceptPartialUpdates(ETrue)
Call RPositioner::SetUpdateOptions()
passing the
options object as a parameter
However, this process has the side-effect of setting all the other update options to their default values as described above. In particular the client request will now not timeout which is unlikely to be the desired behaviour. To avoid this, a client should usually modify the current update options as follows:
Get the current update options by calling
RPositioner::GetUpdateOptions()
Call the appropriate TPositionUpdateOptions::SetXXX()
methods for the options to be changed
Call RPositioner::SetUpdateOptions()
passing the
modified options object as a parameter
The following code shows a simple example of how to set update options. Note that all the options are changed by the client.
...
TPositionUpdateOptions options;
// Frequency of updates in microseconds
const TTimeIntervalMicroSeconds KUpdateInterval(2000000);
// How long the application is willing to wait before timing out the request
const TTimeIntervalMicroSeconds KTimeOut(4000000);
// The maximum acceptable age of the information in an update
const TTimeIntervalMicroSeconds KMaxUpdateAge(1000000);
options.SetUpdateInterval(KUpdateInterval);
options.SetUpdateTimeOut(KTimeOut);
options.SetMaxUpdateAge(KMaxUpdateAge);
options.SetAcceptPartialUpdates(EFalse);
User::LeaveIfError(positioner.SetUpdateOptions(options));
/* Now when the application requests location information
it will be provided with these options */
positioner.NotifyPositionUpdate(posInfo, status);
...
The following code example shows an example of how to change one update option (to accept partial updates).
...
TPositionUpdateOptions options;
User::LeaveIfError(positioner.GetUpdateOptions(options));
options.SetAcceptPartialUpdates(ETrue);
User::LeaveIfError(positioner.SetUpdateOptions(options));
// The other update options are unchanged
positioner.NotifyPositionUpdate(posInfo, status);
...
Notes
When a call to RPositioner::NotifyPositionUpdate()
or RPositioner::GetLastKnownPosition()
completes, it is
necessary to re-issue the request by calling one of these methods again to
obtain further updates even if
RPositioner::SetUpdateOptions()
has been called. Setting
update options allows a client to specify when the next position update is
required, but does not cause periodic requests to the location server to be
made.
A client application can only have one outstanding request for location
information per RPositioner
subsession. An attempt to make a
second request for location information while one is still outstanding causes a
panic to occur. An application must cancel an outstanding request before it
makes another request. This process is described in step 7.
An application can call one of two methods to obtain position data:
RPositioner::NotifyPositionUpdate()
A client application calls
RPositioner::NotifyPositionUpdate()
to request a position
update. The LBS subsystem can either request that a positioning module obtains
a new position and returns it to the client or simply returns an existing
position calculated at some earlier time. The precise action taken by LBS
depends on the quality of position required by the client because it is
possible that a position obtained some time ago may meet the client
application's position quality requirements.
RPositioner::NotifyPositionUpdate()
is a client-server
asynchronous call. The client application can pass any position info class that
derives from TPositionInfoBase
. The standard position info
class is TPositionInfo
which is supported by all
positioning technology modules. An application can get extended location
information (if there is a module that can supply it) by passing one of the
specialised position info classes such as TCourseInfo
or
TPositionSatelliteInfo
instead of
TPositionInfo
.
See Position data and info classes for more information about position data and wrapper info classes.
RPositioner::GetLastKnownPosition()
A client application calls
RPositioner::GetLastKnownPosition()
to request the
device's last known position.
RPositioner::GetLastKnownPosition()
is a client-server
asynchronous call. Calling this method does not instigate a new position fix
even if the LBS subsystem does not have a last known position. It is therefore
possible that this method will fail to return a position if one was not
previously calculated. Client applications must check for this possibility by
checking the values of TCoordinate::Latitude()
and
TCoordinate::Longitude()
of the TPosition
object inside of the TPositionInfo
parameter. If latitude
and longitude data are not available they are set to NaN
(Not a
Number). An application may also need to check the timestamp of the information
to ensure it still meets its needs as it is possible that the last position
update was obtained some time ago.
If the LBS subsystem has a position from a previous request a call
to RPositioner::GetLastKnownPosition()
is more efficient
in terms of request response time and device power consumption. It may also be
cheaper for the mobile device owner who may be charged to obtain a new
position.
When LBS obtains a position the client's TRequestStatus
variable is updated and the TPositionInfoBase
parameter contains
the position data. Client applications must always check the value of the
TRequestStatus
parameter as this indicates the success or failure
of the location request and may indicate that specified location accuracy
criteria could not be satisfied at the time of the request.
The value of TRequestStatus
that is set when a position
update occurs or times out depends on the configuration of the LBS subsystem.
See Location Acquisition API runtime behaviour for more information.
When the location server obtains a position, the client's
TRequestStatus
variable is updated. In the example, the
TPositionInfo
object that was passed to
RPositioner::NotifyPositionUpdate()
holds the new position
data in a TPosition
object.
Important notes
An application should test what kind of position is returned by
NotifyPositionUpdate()
.
TPositionInfoBase::PositionMode()
returns a bitmask value
of type TPositionModuleInfo::TTechnologyType
that is
composed of values of type
TPositionModuleInfo::_TTechnologyType
. Valid combinations
of this value are as follows:
TPositionInfoBase::PositionMode() | Meaning |
---|---|
ETechnologyNetwork |
A reference position obtained from the network |
ETechnologyTerminal | ETechnologyAssisted |
A position calculated using GPS with assistance data from the network |
ETechnologyNetwork | ETechnologyAssisted |
A position calculated using GPS measurements by a remote server in the network |
ETechnologyTerminal |
A position calculated using GPS without assistance data (autonomous mode) |
A reference position may be returned to a client application by the location server before a more accurate position fix is available. Whether a reference position is made available to the location server depends on the implementation of the positioning modules by the Symbian OS licensee or handset manufacturer.
If a reference position is returned, the behaviour is as follows:
For the first call to RPositioner::NotifyPositionUpdate()
NotifyPositionUpdate()
completes and a reference
position is returned to the client. The client application can check
for return of a reference position by checking for
TPositionInfoBase()::PositionMode() ==
TPositionModuleInfo::ETechnologyNetwork
. If a reference position is
returned it may not satisfy the application's position accuracy quality
criteria and the application will need to make another
NotifyPositionUpdate()
request.
For subsequent calls to RPositioner::NotifyPositionUpdate() (made by the same client subsession)
NotifyPositionUpdate()
completes and a position is
returned to the client. This position may be either:
Calculated in the mobile device by GPS with assistance data (for Terminal Based Mode)
TPositionInfo::PositionMode() ==
TPositionInfoBase::ETechnologyTerminal |
TPositionInfoBase::ETechnologyAssisted
Returned from the network, a position known as the final network position (for Terminal Assisted Mode)
The value of TPositionInfo::PositionMode()
for
a final network position depends on the configuration of the LBS subsystem:
Normal behaviour is to return TPositionInfo::PositionMode()
== TPositionModuleInfo::ETechnologyNetwork |
TPositionModuleInfo::ETechnologyAssisted
, but it is possible for LBS to
return TPositionModuleInfo::ETechnologyTerminal |
TPositionModuleInfo::ETechnologyAssisted
if it is configured to do so.
See Location Acquisition API runtime behaviour for more information.
Note that NotifyPositionUpdate()
may complete early if a
GPS positioning module signals to LBS that it will be unable to return a
location fix with the required quality criteria. In this case the Location
Server returns the best location fix it can obtain to the client. The value of
the TRequestStatus
parameter of the client is set to either
KPositionQualityLoss
or KErrNone
depending on the
configuration of Location Acquisition API runtime behaviour.
A position update timeline for tracking is shown in figure 2. Note that
this diagram shows the timing of updates provided by the Location Server
lbslocserver.exe
that has been part of the LBS subsystem since
Symbian OS v9.2. The exact behaviour of tracking on platforms that use a
Location Server for S60 may differ from that shown in Figure 2.
A client application has previously called
TPositionUpdateOptions::SetUpdateInterval(T)
and
RPositioner::SetUpdateOptions()
(not shown in figure 2). Partial
updates are not set. LBS is also configured to return reference positions and
accurate positions only (see Location Acquisition API runtime behaviour for more information about this behaviour). The important
points are:
A client application makes its first call to
RPositioner::NotifyPositionUpdate()
(First NPUD in figure 2).
After a time t, the client's RunL()
method is called
and it receives its first position update (the reference position update Ref
Pos in figure 2). This first position update is delivered to the client by LBS
as soon as possible (t is as short as possible and is not equal to T). The
client then makes its next call to NotifyPositionUpdate()
(the
next NPUD in figure 2). When tracking, a client application should make its
next call to RPositioner::NotifyPositionUpdate()
as soon as
possible in its RunL()
method. The time between the client's
RunL()
and the client's next NPUD is exaggerated for clarity in
Figure 2.
At a time t + T (where T is the update interval) the client's
RunL()
method is called and it receives the next position update
(GPS Pos in figure 2). The client makes its next call to
NotifyPositionUpdate()
.
The next position update is expected at time t + 2T, but in the case shown in figure 2 this is not possible (the mobile device may have moved into an area where the GPS signal is weak). In general if it is not possible to obtain an accurate GPS fix by time t + nT, but the fix is obtained a short time later, the next position update is delivered as soon as possible after time t + nT (after t + 2T in figure 2).
The client makes its next call to
NotifyPositionUpdate()
and at time t + (n+1)T the next position
update is delivered (at t + 3T in figure 2).
The important point to note is that LBS attempts to deliver position updates at regular times t + nT but the time interval between position updates may temporarily be greater than or less than T.
Note that if partial updates were enabled, an incomplete position would be delivered at time t + 2T if it were available. Also note that an inaccurate position would be delivered if one was available at that time and LBS was configured to return it.
The value of a client's TRequestStatus
can be set to an
LBS error code (defined in lbserrors.h
) or an error code
defined in a licensee's positioning module. An error causes
NotifyPositionUpdate()
to complete. An application should always
check the value of TRequestStatus
when its RunL()
method is called.
To cancel a location request a client application calls
RPositionerSubSessionBase::CancelRequest()
, passing a
EPositionerNotifyPositionUpdate
parameter. The client's
TRequestStatus
is set to KErrCancel
if the request
was successfully cancelled and no position update is returned.
To complete a location request early, a client application calls
RPositionerSubSessionBase::CompleteRequest()
passing a
EPositionerNotifyPositionUpdate
parameter. Calling this
method does not cancel the position update, but asks the location server to
return any available position data. The returned position update may be
different from that which would have been returned if the request had been
allowed to complete normally. If the request is completed early, the client's
TRequestStatus
is set to KPositionEarlyComplete
. Note
that this method is not implemented on the S60 platform and returns
KErrNotSupported
.
RPositioner::Close()
closes the subsession.
RPositionServer::Close()
closes the server session. In the
code example the cleanup stack function is used. Any privacy requester objects
created by a client must also be cleaned up.