Make Location Aware Apps Part of the Grind with BREW

Make Location Aware Apps Part of the Grind with BREW

hile Qualcomm BREW has had support for location-based services (LBS) applications since its inception, only recently have CDMA carriers begun to roll out the back-end support these applications need. Consequently, the BREW LBS interface may be one of the least-used and least-understood interfaces available to handset developers. Yet, in the coming year these may be the most in-demand as application developers race to bring location-awareness to their applications.

Introducing the IPosDet Interface
Since its inception, Qualcomm BREW has provided some form or another of LBS support. Beginning in BREW 1.1, Qualcomm added the IPosDet interface, a versatile asynchronous interface for obtaining both traditional latitude/longitude and cellular base station location information (most applications will use the traditional latitude/longitude based positioning, because this is the easiest way to interface with back-end geocoded databases). This interface provides direct access to the handset’s assisted Global Positioning System (GPS) facility gpsOne, in which the handset monitors both the cellular network and GPS satellite signals and offloads expensive processing to location servers on the network, permitting location fixes with as little as one cell site and one GPS satellite’s worth of data.

Because BREW handsets use Qualcomm’s gpsOne-assisted GPS facility, carriers must upgrade their infrastructure by adding the necessary location servers. Consequently, LBS applications have been slow to appear, because carriers must first pave the way for the applications by upgrading their networks to support these applications. Nonetheless, for many carriers this work is almost complete, and for registered developers, Qualcomm can provide flash updates to specific handsets that enable the IPosDet interface for application testing on many major carriers.

The IPosDet interface provides these methods:

  • IPOSDET_SetGPSConfig and IPOSDET_GetGPSConfig let you set and get the configuration information for the accuracy and kind of position information you seek.
  • IPOSDET_GetSectorInfo returns information about the cellular network and the handset’s location in the network, including the cell system ID, network ID, base station ID, and base station class. It’s best used for network diagnostic applications when you’re working directly with carriers on specific applications and you have access to a database that describes the deployed network.
  • IPOSDET_GetGPSInfo is an asynchronous interface which returns latitude, longitude, altitude, velocity, and heading through a callback you register with the interface.

Because location information is a sensitive topic, with serious repercussions for user privacy, the IPosDet interface requires privileges in the application’s Module Information File (MIF). If you’re developing an LBS application that will fetch latitude/longitude information, be sure to assert the Position Determination Privilege; similarly, if you’re going to be using IPosDet to obtain sector positioning information, you must assert the Sector Info privilege. In the BREW MIF Editor (version 3.0), simply choose the “Privileges” tab and check either the “Position Location” or “Access to Sector Location” items. Don’t forget to document this privilege use in your National Software Testing Laboratories (NSTL) submission, too, to ensure there aren’t any questions when you apply for True BREW certification of your application. Moreover, as you will see in the section “Obtaining Position Information” later in this article, actually requesting a position causes most handsets to show a dialog telling the user that the application is requesting positioning information, giving them the opportunity to deny the request.

Creating, Configuring, and Destroying IPosDet
The IPosDet interface is a traditional BREW interface, created using ISHELL_CreateInstance:

if ( SUCCESS != ISHELL_CreateInstance( pIShell, AEECLSID_POSDET,                                        (void **)&pMe->pIPos ) ){  return EFAILED;}

When you’re done using the interface, you must release it as well, using IPOSDET_Release:

if( pMe->pIPos )  IPOSDET_Release( pMe->pIPos );

Of course, because it’s a standard BREW interface, you can also cross-cast to IBase and use IBASE_Release, or the RELEASEIF macro that you can find in many of the Qualcomm sample applications which does essentially the same thing.

Before you use an IPosDet instance to obtain positioning information, you must configure it using IPOSDET_SetGPSConfig, which takes an AEEGPSConfig structure with the following members:

There’s a correlation between the time interval between position reports and accuracy?the smaller the interval between position requests, the larger the potential error in the result.
  • The nFixes field indicates the number of fixes you desire when invoking IPOSDET_GetGPSInfo.
  • The nInterval field indicates the number of seconds between position reports you desire when invoking IPOSDET_GetGPSInfo.
  • The optim field indicates the tradeoff between position accuracy and speed you require, and is a constant, such as AEEGPS_OPT_NONE (no optimization is required) AEEGPS_OPT_SPEED (optimize positioning data for speed), AEEGPS_OPT_ACCURACY (optimize for position accuracy), or AEEGPS_OPT_PAYLOAD (optimize for minimum use of the network). It’s typically best to specify AEEGPS_OPT_DEFAULT, which performs no optimization.
  • The qos field indicates the desired quality of service, and is a range from 0-255. Not all handsets use this field.
  • The server field is a structure that identifies the type and address of the server; most applications should simply specify AEEGPS_SERVER_DEFAULT in the svrType member of this structure.

Deciding what value to use for the mode field is somewhat tricky, because the IPosDet interface can return either a single position report (called a one-shot operation) or can return a series of positions over time, for use in tracking and navigation applications. The mode field can have one of these values:

  • AEEGPS_MODE_ONE_SHOT: This returns only a single position determination.
  • AEEGPS_MODE_DLOAD_FIRST: This uses the network to contact an LBS server for the first position request, and then performs subsequent position requests using only the handset’s capabilities. Use this value in tracking or navigation applications where initial accuracy is key.
  • AEEGPS_MODE_TRACK_LOCAL: This minimizes network use for applications requiring frequent rapid position, velocity, or altitude information.
  • AEEGPS_MODE_TRACK_NETWORK: This utilizes the network for repeated tracking information, providing improved accuracy at the expense of performance.
  • AEEGPS_MODE_TRACK_OPTIMAL: This attempts to honor the optim field to determine the best algorithm for position determination.
  • AEEGPS_MODE_TRACK_STANDALONE: This minimizes dependency on the network and is suitable for use in regions where the cellular network may not be available.
  • AEEGPS_MODE_DEFAULT: This is the default mode of operation, providing a single position determination.

Thus, if you need only a single position report at a time, use AEEGPS_MODE_DEFAULT (or AEEGPS_MODE_ONE_SHOT). If you require multiple position reports?as most navigation or tracking applications do?you need to consider the tradeoff between the time interval between fixes and accuracy. There’s a correlation between the time interval between position reports and accuracy?the smaller the interval between position requests, the larger the potential error in the result. As you develop your application, be sure to allocate time to test the different options in different settings to decide which of the tracking options are right for you.

Obtaining Position Information
Because BREW is essentially single-threaded, interfaces such as IPosDet use callbacks to permit your application to make a request and continue executing. The IPOSDET_GetGPSInfo request does this, meaning that you must register an AEECallback and provide memory for the resulting position information:

static void positionNotify( void *po ){  SGPS  *pThis = (SGPS*)po;  if(  pThis->current.status == AEEGPS_ERR_NO_ERR ||      ( pThis->current.status == AEEGPS_ERR_INFO_UNAVAIL &&         pThis->current.fValid ) )   {    // Do something with the position data here in pThis->current  // Kick off another position request in nInterval seconds.  ISHELL_SetTimer( pThis->pIShell, 1000*pThis->config.nInterval,                    pThis->cbInterval.pfnNotify,                    pThis->cbInterval.pNotifyData);}}void interval( void *po ){  SGPS  *pThis = (SGPS*)po;IPOSDET_GetGPSInfo( pThis->pIPos,                     AEEGPS_GETINFO_LOCATION | AEEGPS_GETINFO_VELOCITY |                     AEEGPS_GETINFO_ALTITUDE,                       pThis->accuracy, &pThis->current, &pThis->cb );}int Start( IGPS *po ){  SGPS  *pThis = (SGPS*)po;    if ( pThis->bRunning ) return EBADSTATE;  pThis->config.mode = AEEGPS_MODE_TRACK_LOCAL;  pThis->config.optim = AEEGPS_OPT_DEFAULT;  IPOSDET_SetGPSConfig( pThis->pIPos, &pThis->config );  CALLBACK_Init( &pThis->cb, positionNotify, pThis );  CALLBACK_Init( &pThis->cbInterval, interval, pThis );  interval( po );  return SUCCESS;}

This code begins with Start, which sets the IPosDet instance to perform local tracking with default optimization, and then sets up two callbacks: the first to handle the returned data from IPOSDET_GetGPSInfo, and the second to repeatedly call IPOSDET_GetGPSInfo for subsequent tracking data. This points to an important source of confusion many have when first working with IPosDet: while you tell the interface whether you’re using it in a single-shot or repeating manner, your application is responsible for calling it each time you need position information. It calls your callback exactly once (if IPOSDET_GetGPSInfo returns SUCCESS) for each time you call IPOSDET_GetGPSInfo.

Start calls interval, which performs a single position determination using the configuration set by Start. When invoking IPOSDET_GetGPSInfo, you must pass the request type (indicating what combination of location, velocity, and altitude you desire), the desired accuracy (a constant from AEEGPS_ACCURACY_LEVEL1 to AEEGPS_ACCURACY_LEVEL6, or simply use AEEGPS_ACCURACYLEVEL_LOWEST or AEEGPS_ACCURACY_LEVEL_HIGHEST), where to store the result, and the callback to invoke when the location determination completes.

At this point, the control passes back to your BREW application, with a caveat: upon the first use of a fresh IPosDet interface, many handsets will prompt the user to determine if they wish to have the location service determine their location. This uses BREW’s Dialog interface, so you must be prepared to surrender the screen after invoking IPOSDET_GetGPSConfig, and wait until you receive an EVT_DIALOG_END event. Then, upon receiving EVT_DIALOG_END, you need to repaint the screen with whatever contents it held prior to invoking IPOSDET_GetGPSConfig. Typically, the dialog that appears is a yes/no dialog; in the event that the user rejects the LBS attempt, the callback invoked by IPOSDET_GetGPSConfig will return an error code instead of valid positioning data. This callback, positionNotify, looks at the results from the IPosDet interface, and is located where you’d process the position results (perhaps posting an event to your application to do additional processing after the callback completes). Once positionNotify finishes with the position information, it uses ISHELL_SetTimer to schedule another position request.

It’s worth observing the use of memory in this code, too. Notably, the AEECallback structures and the result memory in which IPosDet returns its data (pThis->current, an AEEGPSInfo structure) must be allocated on the heap, not the stack, because they must remain in scope once the Start function exits (and the IPOSDET_GetGPSInfo method, for that matter). While obvious to experienced BREW developers, it’s a common pitfall among many newcomers, especially those unaccustomed to the asynchronous nature of most of the BREW interfaces.

IPOSDET_GetGPSInfo fills the AEEGPSInfo structure you provide with the data obtained. These fields are fairly self-explanatory and well-documented, but a few comments are in order. First, not all fields may be filled; you must examine the fValid field to determine which fields contain valid data. This field is a bit field of flags, one for each field in the structure, binary-ORed to indicate which fields have valid data.

Second, coordinate data is returned as a scaled fixed-point number stored as an integer, not a floating-point number. If you need floating-point latitude and longitude data, you’ll need to convert it yourself; the relationship is:

lat = ( dwLat * 180 ) / 33554432 lon = ( dwLon * 360 ) / 67108864
Author’s Note: You can also use the WGS84_TO_DEGREES helper thoughtfully included in BREW 2.1.

Latitude and longitude are returned in the now-ubiquitous WGS-84 ellipsoid datum, which means that the coordinate data matches that reported by default on most consumer GPS receivers and most, if not all, modern maps. Similar coordinate conversions are required for the heading data and velocity?consult the documentation for details.

Finally, don’t forget to check the status field before attempting to use the data at all; it indicates whether the request succeeded or failed, and includes details about the kind of failure, such as a general failure, a timeout to a specific request, or if the request was rejected for privacy reasons.

A Valuable Skill to Have
With a growing market for LBS, now’s the time to become familiar with BREW’s IPosDet interface. The interface isn’t complex, although you need to keep in mind a few things:

  • The interface operates asynchronously, so you must provide a callback to receive position information, and design your LBS application with that in mind.
  • For best results, you must select the options you pass to IPOSDET_GetGPSInfo deserve careful consideration with respect to your application’s use of IPosDet. Be especially careful when selecting either single-shot or tracking options.
  • IPOSDET_GetGPSInfo returns only a single position report, regardless of whether you select single-shot or tracking operation. It’s up to you to poll this request at an appropriate time interval if you’re building an application that tracks position.

With these facts well in hand, you shouldn’t have a problem integrating LBS in your applications!


About Our Editorial Process

At DevX, we’re dedicated to tech entrepreneurship. Our team closely follows industry shifts, new products, AI breakthroughs, technology trends, and funding announcements. Articles undergo thorough editing to ensure accuracy and clarity, reflecting DevX’s style and supporting entrepreneurs in the tech sphere.

See our full editorial policy.

About Our Journalist