Location Acquisition API: Using Location Acquisition API

Usage Overview

The following steps are to be followed when using Location Acquisition API for a simple positioning operation. This is to provide the application developer with general idea of how to use Location Acquisition API. It is not intended as programming example.

  1. Connect to Location Server: RPositionServer.
  2. Create a sub-session with Location Server to retrieve location updates: RPositioner.
  3. Inform Location Server who is requesting the location information: RPositioner::SetRequestor().
  4. Set the update options (if needed e.g. to obtain periodic updates): RPositioner.
  5. Request to be informed (asynchronously) of position updates: RPositioner. As a standard, NotifyPositionUpdate() takes the parameters TPositionInfo and a TRequestStatus.
  6. After the request has been completed the location information is stored in TPositionInfo, and TRequestStatus contains the result of the request.
  7. Extract the current position: TPositionInfo.
  8. Re-issue the request to obtain the next position update: RPositioner.
  9. Cancel the ongoing request(s): RPositioner and RPositionServer.
  10. Close the sub-session: RPositioner.
  11. Close the Location Server session: RPositionServer.

Client-server communication

As Location Acquisition API is a client-server interface, a client has to set up a connection to Location Server by calling RPositionServer to get location estimates. According to the common Symbian client/server API scheme, the RPositioner class represents a sub-session to Location Server. The class provides a set of OpenL() methods to define additional parameters of the newly opened sub-session: whether to use the default module, a particular module or a module that conforms to the client’s criteria. Using a particular positioning module by specifying the criteria is not supported.

Most location activity is done through RPositioner. The actions on getting general Location Server information are covered by RPositionServer. See the following paragraphs on how to use these classes.

To close a sub-session, the RPositioner method is provided. After the use of Location Server, RPositionServer must be called to close the client/server connection. All the used resources are freed at that moment.

In the same way as with several other Symbian OS interfaces, only one request can be outstanding on each asynchronous method. For example, it is not allowed for an application to call NotifyPositionUpdate() before all the previous requests on that method have been completed. If the application wishes to call the same method before all the outstanding requests complete normally, it must first attempt to cancel those requests. The application must wait until the cancellation has been confirmed and then re-issue the desired request.

When a client application wishes to close one of its connections to RPositionServer, there can be no outstanding requests on that particular connection. If a client application attempts to close a connection before outstanding requests have been cancelled or completed, it is panicked. If the application wishes to close a RPositioner sub-session, it must ensure that it has successfully cancelled requests to GetLastKnownPosition() and NotifyPositionUpdate(). If the application wishes to close the main RPositionServer session, it must have successfully cancelled the NotifyModuleStatusEvent() request.

Privacy handling

Determining of someone’s location is a question of the person’s privacy and security. The Symbian OS and Positioning Framework provide a number of safeguards to help prevent the misuse of location information. Location information is not given to a requestor unless the user of the device for which location is requested accepts it. For example, if user A requests the location of user B, acceptance of user B is required to send the location information to user A. User B can accept or deny the particular request, based on the requestor’s information, which is provided by Positioning Framework. Positioning Framework requires the information about the client using Location Acquisition API.

There are two requestor types: service requestors and contact requestors. A service requestor represents any terminal or network application or service, and a contact requestor represents an individual person requesting the location. CRequestor defines the type of the requestor.

The requestor information must be sent to Location Server before requesting location estimates (otherwise, all such requests fail). This may be done in two different ways:

  1. Single Requestor: May be defined by RPositioner, its three-argument variant. In this case, the requestor is defined directly by the values supplied to the function’s parameters. This case is used by applications or services if they are the only request source
  2. Stack of Requestors: Specifying requestor information through the stack of requestors by calling the second variant of RPositioner, which gets an argument of the type RRequestorStack. This approach is used more often when a request is made by an application or service on behalf of some other entity, such as a contact or some other application.

RRequestorStack is a container for a list of the requestors on behalf of which the request is made. Each particular requestor in the stack is represented by a CRequestor class.

Regardless of the number of requestors, there is always one service requestor, because the application executing the location request must be always shown, even if it made the request on behalf of a contact requestor. For this reason, the last item in the requestor stack must always be a service requestor.

Security and capabilities

From S60 release 3.0 onwards platform security rules are enforced. The client application must have the Location capability to use some of methods from the API, related to client-server communication. These methods are:

All the other methods from the API do not require any capabilities.

Location update options

In some cases, a client may need to specify more criteria for how location updates should be generated, what data should be considered as valid or not and so on. The RPositioner function allows to specify such criteria via the TPositionUpdateOptions class. Location update options affect only RPositioner. The TPositionUpdateOptions class provides the following options:

Extended location information

In addition to the general position classes introduced in Security and capabilities, there are two other position classes: TPositionCourseInfo and TPositionSatelliteInfo.

TPositionCourseInfo contains a TCourse object, which may be used to get information such as the current speed at which the device is moving, the device’s direction in terms of bearing, and also the accuracy of these parameters.

TPositionSatelliteInfo contains information about the satellites used in locating: how many satellites are available, which of those were used to produce the current estimate, and a list of the satellites with their data. A satellite is represented by the TSatelliteData class.

A client gets the information by sending the appropriate object to Location Server via NotifyPositionUpdate(). If the currently used positioning module supports the data (see Module Information), it fills the objects with the data and returns it to the client. TPositionSatellites inherits TPositionCourseInfo, which is derived from the TPositionInfo class, and thus the client gets the extended information simultaneously with the general data in one request. However, if the module does not support the requested data class, the whole request fails. Therefore, the client should ensure if the particular position information class is supported by the current module before it issues a request.

Module information

RPositionServer also provides the methods GetModuleInfoByIndex() and GetModuleInfoById() to get information about the currently available modules. Modules are identified by the TPositionModuleId class and its data is provided in the format of the TPositionModuleInfo class. To know the state of a particular module at a given moment, GetModuleStatus() may be called. To receive all module status events, the NotifyModuleStatusEvent() member function is used.

The module information is delivered in the form of the TPositionModuleInfo class. The most important fields are the following:

The TPositionModuleEvent class is used to hold information about the module when a client is informed about events in the module. This is also used by clients to specify of which types of events happening in the module they wish to be notified. Clients use this class to determine what particular events have just occurred and the new status of the module.

Units of measurement and coordinates

Location Acquisition API defines a number of standard classes for holding position information. Unless otherwise stated, these classes use the following measurement system:

Unassigned values

A number of the classes described in this document use real numbers to hold position, accuracy and other information. Sometimes some values can be unset. Altitude is a typical example.

Where a real number has not been assigned, Location Framework indicates this by a special (reserved) bit pattern. This bit pattern is defined by Symbian OS and is usually referred to as “Not a Number” (NaN). Applications should check if a value is NaN by using the standard method from the Math library (Math::IsNaN).

Although NaN can be tested, the value cannot be used in calculations. Attempting to use a NaN value in an arithmetic expression results in an application panic.

Obtaining current location estimate

In order to perform a simple location request, a client establishes a connection with the RPositionServer and opens a sub-session with positioner. Then, it sets information about the requestor and calls the asynchronous RPositioner function to get location information. After getting location information, the client closes the sub-session and connection with RPositionServer.

The following diagram illustrates the steps involved in simple obtaining of location information.

Figure 7: Obtaining current location information:

The following simple example shows the code that a client should execute to get a position update.

#include <lbs.h>

  // Connect to server and create a session
  RPositionServer server;
  RPositioner positioner;
  User::LeaveIfError(server.Connect());
  CleanupClosePushL(server);
  // use default positioning module
  User::LeaveIfError(positioner.Open(server));
  CleanupClosePushL(positioner);

  // Set the Requestor information
  _LIT(KCntPhone, "+358501234567");
  _LIT(KSrvName, "MyService");
  RRequestorStack stack;
  CRequestor* contact = CRequestor::NewLC( CRequestor::ERequestorContact, CRequestor::EFormatTel  ephone, KCntPhone);
  stack.Append(contact);
  CRequestor* service = CRequestor::NewLC(CRequestor::ERequestorService,	CRequestor::EFormatAppl   ication, 	KSrvName);
  stack.Append(service);
  User::LeaveIfError(positioner.SetRequestor(stack));
  //Issue a Location Request
  TRequestStatus status;
  TPositionInfo posInfo;
  positioner.NotifyPositionUpdate(posInfo, status); // asynchronous request
  User::WaitForRequest(status); // for exemplification only, AOs should be used
  User::LeaveIfError(status.Int());
  //Use the location information present in the posInfo object
  //Cleanup
  stack.Reset();
  CleanupStack::PopAndDestroy(service);
  CleanupStack::PopAndDestroy(contact);
  CleanupStack::PopAndDestroy(&positioner); // this will call Close() method
  CleanupStack::PopAndDestroy(&server); // this will call Close() method

Obtaining extended location estimate

In order to obtain extended location information, the client needs to specify what kind of information it expects from Location Server before issuing the request. This is specified by the setting identifiers of the requested fields in the HPositionGenericInfo object: The TPositionFieldId specifies the various fields that can be requested.

The following diagram illustrates the steps involved in obtaining extended location information.

Figure 8: Obtaining extended location information:

The following example depicts the code that a client should execute to get extended location information

  //Connect to the server and open a session
  RPositionServer server;
  RPositioner positioner;
  User::LeaveIfError(server.Connect());
  CleanupClosePushL(server);
  TPositionModuleId moduleId;
  moduleId.iUid = KModuleIdThatSupportsAddressCapabilites; // select valid module
  User::LeaveIfError(positioner.Open(server, moduleId)); // use specific module
  CleanupClosePushL(positioner);
  //Init Generic Info buffer
  HPositionGenericInfo* genInfo = HPositionGenericInfo::NewLC(); // default sizes
  genInfo->SetRequestedField(EPositionFieldCountry);
  genInfo->SetRequestedField(EPositionFieldCity);
  // Specify Requestors
  _LIT(KSrvName, "MyService");
  RRequestorStack stack;
  CRequestor* service = CRequestor::NewLC(
			CRequestor::ERequestorService,
			CRequestor::EFormatApplication,
			KSrvName);
  stack.Append(service);
  User::LeaveIfError(positioner.SetRequestor(stack));
  // Make a request
  TRequestStatus status;
  positioner.NotifyPositionUpdate(*genInfo, status);
  User::WaitForRequest(status);
  User::LeaveIfError(status.Int());
  // Get Results
  TPtrC16 city, country;
  if (genInfo->IsFieldAvailable(EPositionFieldCountry))
	  {
   	genInfo->GetValue(EPositionFieldCountry, country);
   	}
  if (genInfo->IsFieldAvailable(EPositionFieldCity))
	  {
   	genInfo->GetValue(EPositionFieldCity, city);
	  }
  // Cleanup
  stack.Reset();
  CleanupStack::PopAndDestroy(service);
  CleanupStack::PopAndDestroy(contact);
  CleanupStack::PopAndDestroy(genInfo);
  CleanupStack::PopAndDestroy(&positioner); // this will call Close() method
  CleanupStack::PopAndDestroy(&server); // this will call Close() method

Obtaining last known position information

To obtain the last known location information, the client application establishes connection with RPositionServer and opens a sub-session using RPositioner. Then, it sets information about the requestor and calls the asynchronous RPositioner function to get cached location information (if any). After getting location information, the client closes the sub-session and connection with RPositionServer.

Following diagram illustrates the steps involved in simple obtaining the last known position information.

Figure 9: Obtaining last known position information:

  #include <lbs.h>
  //Init Connection
  RPositionServer server;
  RPositioner positioner;
  User::LeaveIfError(server.Connect());
  CleanupClosePushL(server);
  User::LeaveIfError(positioner.Open(server)); // use default positioning module
  CleanupClosePushL(positioner);
  //Specify Requestors
  _LIT(KSrvName, "MyService");

  RRequestorStack stack;
  CRequestor* service = CRequestor::NewLC(
			CRequestor::ERequestorService,
			CRequestor::EFormatApplication,
			KSrvName);
  stack.Append(service);
  User::LeaveIfError(positioner.SetRequestor(stack));
  //Issue a Location Request
  TRequestStatus status;
  TPositionInfo posInfo;

  positioner.GetLastKnownPosition(posInfo, status); // asynchronous request
  User::WaitForRequest(status); // This is just for demonstration. AOs should be used
  User::LeaveIfError(status.Int()); // Analyze Results

  TPosition position;
  posInfo.GetPosition(position);

  stack.Reset();
  CleanupStack::PopAndDestroy(service);
  CleanupStack::PopAndDestroy(contact);
  CleanupStack::PopAndDestroy( &positioner ); // this will call Close() method
  CleanupStack::PopAndDestroy( &server ); // this will call Close() method

Cancelling the request for simple obtaining of a location estimate

The client application can cancel an outstanding asynchronous location request from within the RPositioner class. Canceling requests is typically attempted when an application is closing down.

The following diagram illustrates the steps involved in cancelling the location request.

Figure 10: Cancelling the request for location information

  #include <lbs.h>

  // CLocationOp is an Active Object and derives from CActive class
  // In the construction of the object connect to the server
  // and create the iPositioner session
  void CLocationOp::RequestLocation()
  {
  // Make an asynchronous request for current location
  iPositioner.NotifyPositionUpdate( iPosInfo, iStatus );
  SetActive();
  }

  void CLocationOp::DoCancel()
  {
  iPositioner.CancelRequest( EPositionerNotifyPositionUpdate );
  }

  void CLocationOp::RunL()
  {
  // Handle the response for the NotifyPositionUpdate.

  }

Getting periodic position updates

The client application can modify the behavior of location requests. For example after establishing connection with RPositionServer and opening a sub-session using RPositioner, client can specify periodic update interval through location update option and then requests for the location information. After getting the information client re-issues a request for location information and it gets back the information after the specified time-interval.

The following diagram illustrates the steps involved in getting the periodic position updates.

Figure 11: Getting periodic position updates

  //Connect to the server and create a session
  TInt updateIntervalTime = KUpdateInterval; // Client should define the KUpdateInterval
  TPositionUpdateOptions updateOptions;
  updateOptions.SetUpdateInterval(TTimeIntervalMicroSeconds(aIntervalTime));
  User::LeaveIfError( iPositioner.SetUpdateOptions(updateOptions) );

  // Further calls to NotifyPositionUpdate will use this UpdateInterval option
  TPositionInfo posInfo;
  TRequestStatus status;

  iPositioner.NotifyPositionUpdate(posInfo, iStatus);
  User::WaitForRequest(status);
  User::LeaveIfError(status.Int());

  // Use the information in posInfo

  // make another request for current Location
  iPositioner.NotifyPositionUpdate(posInfo, iStatus);

  // The client will receive a response for the above request
  // upon the elapse of the specified interval
  User::WaitForRequest(status);
  User::LeaveIfError(status.Int());

  // Use the information in posInfo
  // Close the session and connection to the server finally

Position update with time-out

Client application can specify the time period for how long it is prepared to wait to obtain a fix. The timeout period starts when the client application issues a location request. If an update is not obtained within this time period, NotifyPositionUpdate() completes with KErrTimedOut.

When the client changes the update timeout it does not affect the current location request. The updated timeout interval is applied on further current location requests from the client.

Invoking SetUpdateOptions() with an update timeout value of zero sets it to the default behavior, which is to have no time limit.

The following diagram illustrates the steps involved in getting the position updates with time-out specified.

Figure 12: Position update with time-out

  //Connect to the server and create a session

  TInt updateTimeout = KUpdateTimeout; // Client should define the KUpdateTimeout
  TPositionUpdateOptions updateOptions;
  updateOptions.SetUpdateTimeOut( TTimeIntervalMicroSeconds(updateTimeout) );
  User::LeaveIfError( iPositioner.SetUpdateOptions(updateOptions) );

  // Further calls to NotifyPositionUpdate will use this Update Timeout value
  TPositionInfo posInfo;
  TRequestStatus status;

  iPositioner.NotifyPositionUpdate(posInfo, iStatus);
  User::WaitForRequest(status);

  // Now if the Location Server is unable to return a position information within the
  // specified update time then it returns KErrTimedOut
  User::LeaveIfError(status.Int());

  // Use the information in posInfo

  // Close the session and connection to the server finally

Getting the module information

Information about the currently available modules can be obtained using RPositionServer and RPositionServer methods. For more details about the kind of module information topic Module Information section can be referred.

The following diagram illustrates the steps involved in getting the module information.

Figure 13: Getting the module information

  #include <lbs.h>

  //Init Connection
  RPositionServer server;

  User::LeaveIfError(server.Connect());
  CleanupClosePushL(server);

  TPositionModuleInfo moduleInfo;

  //KModuleIndex should be within the
  //range of 0 to server.GetNumModules() - 1
  TInt moduleIndex = KModuleIndex;
  User::LeaveIfError( server.GetModuleInfoByIndex( moduleIndex, moduleInfo ) );
  // Use the module information here.

  CleanupStack::PopAndDestroy( &server ); // this will call Close() method

Using specific positioning module for position information

Location requests can be obtained using a specific positioning module. This is achieved by specifying the module ID as a parameter while opening the subsession using RPositioner.

The following diagram illustrates the steps involved in using a specific positioning module for getting the position information.

Figure 14: Using specific positioning module for position information

  #include <lbs.h>
  ...
  //Init Connection
  RPositionServer server;
  RPositioner positioner;
  User::LeaveIfError(server.Connect());
  CleanupClosePushL(server);
  TPositionModuleId moduleId;

  //Use the module Id of the positioning module from which
  //position information is to be requested.
  moduleId.iUid = KInterestedPositioningModuleId;

  //request Location server to use a specific positioning module
  User::LeaveIfError(positioner.Open(server, module));
  CleanupClosePushL(positioner);
  //Specify Requestors
  _LIT(KSrvName, "MyService");

  RRequestorStack stack;

  CRequestor* service = CRequestor::NewLC(
			CRequestor::ERequestorService,
			CRequestor::EFormatApplication,
			KSrvName);
  stack.Append(service);
  User::LeaveIfError(positioner.SetRequestor(stack));
  //Issue a Location Request
  TRequestStatus status;
  TPositionInfo posInfo;

  positioner.GetLastKnownPosition(posInfo, status); // asynchronous request
  User::WaitForRequest(status); // This is just for demonstration. AOs should be used
  User::LeaveIfError(status.Int()); // Analyze Results

  TPosition position;
  posInfo.GetPosition(position);

  stack.Reset();
  CleanupStack::PopAndDestroy(service);
  CleanupStack::PopAndDestroy(contact);
  CleanupStack::PopAndDestroy(&positioner); // this will call Close() method
  CleanupStack::PopAndDestroy(&server); // this will call Close() method

Requesting notification on positioning module events

Status changes of either a single module or all positioning modules can be reported using the asynchronous method RPositionServer. After a notification has been received, the client application must re-issue the status change request if it wishes to obtain further updates.

The following diagram illustrates the steps involved in requesting notifications on positioning module events.

Figure 15: Specifying the positioning module to get the position information

  RPositionServer server;

  User::LeaveIfError( server.Connect() );
  CleanupClosePushL( server );
  TPositionModuleId moduleId;

  //Using KPositionNullModuleId will notify when the status
  //of any module changes. If notification is required for a specific
  //positioning module then use that module's ID.
  moduleId.iUid = KPositionNullModuleId;
  TPositionModuleStatusEvent moduleEvent;
  TRequestStatus status;

  //request server to notify when the module's status changes.
  server.NotifyModuleStatusEvent( moduleEvent, status, moduleId );
  //Wait till the server sends a notification.
  User::WaitForRequest( status );

  User::LeaveIfError(status.Int());
  //If there is no error then use the moduleEvent to identify
  //the status of the module

  //Close the server connection
  server.Close();

Error handling

Location Acquisition API uses the standard Symbian error reporting mechanism. In case of an irrecoverable error, panics are used. Otherwise, leaves are used or functions return error codes as their return values.

Location Acquisition API uses standard system error codes plus certain errors defined in Location Acquisition API. They can be found in the LbsErrors.h file.

During the client-server communication process the following errors may occur:

However, please note that other (more unusual) error codes are also possible and the application programmer should expect more than the standard error codes presented in this document.

Memory overhead

When using Location Acquisition API, the memory overhead is dependent on the amount of instantiated classes but there are also some cases when extra memory usage can be involved. Nevertheless, the memory usage is always controlled by the client application and there are never any uncontrolled allocations of large amounts of memory that the client cannot prevent or avoid.

When communicating with Location Server, additional buffers are used to for transferring data (mostly related to the requestor information). Also the HPositionGenericInfo class uses a heap to store location data. However, in all cases, the amount of memory is defined by the client and thus can be exactly predicted. After use, the needed additional buffers (if any) are unallocated automatically.

The number of simultaneous sessions and subsessions also has an impact on the overall memory usage. For this reason, unnecessary sessions and sub-sessions should be avoided.

Extensions to the API

Location Acquisition API can be extended by defining new data classes. It is possible to provide new location estimate data structures by deriving new classes from TPositionInfoBase or any of its descendants. A positioning module supporting such a class provides the client with new information.

API usage examples

Applications should use Location Acquisition API appropriately to achieve best user experience and lowest power consumption. The following items are main concerns when requesting location information from the system.

There can be different positioning modules available in the terminal. They are mainly based on two types of positioning technologies.

Unless a client is interested in a specific positioning module, it should always use the default module when requesting location information from the system. When default module is used, the system tries to retrieve location information from all enabled positioning modules based on requested location data and location update options. Requested location data determines what positioning modules are used. For example, if client requests TPositionCourseInfo or TPositionSatelliteInfo, positioning modules that based on network technology are not used.

Using location service has quite dramatic impact on battery life of the mobile phone, especially when integrated GPS positioning module is used. Developers must take power consumption into consideration when using this API. The general rule is to make as less location request as possible. When tracking is needed, always select the largest update interval value that is acceptable. If location fix is not required for a long time (i.e. more than 10 minutes), application should close sub-session to Location Server. Network based positioning module consumes much less energy than GPS based positioning module. So, application can consider of using network based positioning modules whenever possible.

In this section we give examples of using Location Acquisition API of the following types of applications.

Following table shows parameters that each application may use when requests for location information. Note, these values are only recommended ones. Developer shall use this table as a reference and change the parameters based on their own needs.
Table 1: API usage examples
Requested location data (3) Used positioning technology Update interval Update timeout Update maximum age Partial update
Navigation application (navigation mode) TPositionCourseInfo GPS based 1 second 0 (No timeout set) 0 (Does not allow old position information) Not allowed
Tourist guide application TPositionInfo GPS based or network based 0 At least 90 seconds (1) 60 seconds Not allowed
GPS satellite information viewer TPositionSatelliteInfo GPS based 1 second 0 (No timeout set) 0 (Does not allow old position information) Allowed
Fleet-tracking application TPositionInfo GPS based or network based Depends on actual use case (2) At least 90 seconds (1) 60 seconds or depends on actual use case Not allowed

(1) Update timeout value shall be long enough for positioning modules (especially modules based on GPS technology) to give a fix. To improve user experience, cancel functionality might be needed for end user to cancel the location request.

(2) Update interval for fleet-tracking application depends on the actual use case. If the update interval is very long (for example over 10 minutes), it's recommended that the application does not set update interval at all. Instead, it should issue location request based on its own timer. And between location requests, the application should close sub-session to Location Server to improve memory usage and save battery life.

(3) Some applications accept only accurate location estimation. Therefore, to prevent network based positioning modules being used, application may request TPositionCourseInfo or TPositionSatelliteInfo.


Copyright © Nokia Corporation 2001-2008
Back to top