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,
void interval( void *po )
SGPS *pThis = (SGPS*)po;
AEEGPS_GETINFO_LOCATION | AEEGPS_GETINFO_VELOCITY |
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 );
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
) 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 velocityconsult 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!