Export (0) Print
Expand All

Responding to Location Report Events

The Location API provides event notifications through callback interfaces. This section provides example code for handling report events.

The following is a sample declaration of a callback object that implements ILocationEvents.



// LocationCallback.h
class CLocationEvents :
    public CComObjectRoot,
    public ILocationEvents 
{
public:
    CLocationEvents() : m_previousTime(0) {}
    virtual ~CLocationEvents(){}

    DECLARE_NOT_AGGREGATABLE(CLocationEvents)

    BEGIN_COM_MAP(CLocationEvents)
        COM_INTERFACE_ENTRY(ILocationEvents)
    END_COM_MAP()

    // ILocationEvents

    // This is called when there is a new location report.
    STDMETHOD(OnLocationChanged)(REFIID reportType,
                                 ILocationReport* pLocationReport);

    // This is called when the status of a report type changes.
    // The LOCATION_REPORT_STATUS enumeration is defined 
    // in Locationapi.h in the SDK
    STDMETHOD(OnStatusChanged)(REFIID reportType,
                               LOCATION_REPORT_STATUS status);
private:
    // We store the previous report timestamp here,
    // and use this when computing the time between the current and previous report
    ULONGLONG m_previousTime;
};

The following is an example implementation of ILocationEvents corresponding to the previous declaration. The ILocationEvents::OnLocationChanged callback function is called each time a location report event arrives. The following implementation of OnLocationChanged handles latitude/longitude report events, and prints out the time stamp and time since the last report. It also prints out the latitude, longitude, altitude, error radius, and altitude error.



// LocationCallback.cpp
#include "LocationCallback.h"

// This is called when there is a new location report.
STDMETHODIMP CLocationEvents::OnLocationChanged(REFIID reportType, 
    ILocationReport* pLocationReport)
{
   // If the report type is a Latitude/Longitude report 
   // (as opposed to IID_ICivicAddressReport or another type)
   if (IID_ILatLongReport == reportType)
   {
      CComPtr<ILatLongReport> spLatLongReport;
      // Get the ILatLongReport interface from ILocationReport
      if ((SUCCEEDED(pLocationReport->QueryInterface(IID_PPV_ARGS(&spLatLongReport)))) 
            && (NULL != spLatLongReport.p))
      {

         // Print the Timestamp and the time since the last report.
         SYSTEMTIME systemTime;
         if (SUCCEEDED(spLatLongReport->GetTimestamp(&systemTime)))
         {
            // Compute the number of 100ns units that difference between 
            // the current report's time and the previous report's time.
               ULONGLONG currentTime = 0, diffTime = 0;
               if (TRUE == SystemTimeToFileTime(&systemTime, (FILETIME*)&currentTime))
               {
                    diffTime = (currentTime > m_previousTime) ? (currentTime - m_previousTime) : 0;
               }

                printf("Timestamp: YY:%d, MM:%d, DD:%d, HH:%d, MM:%d, SS:%d, MS:%d [%I64d] UTC\n",
                    systemTime.wYear,
                    systemTime.wMonth,
                    systemTime.wDay,
                    systemTime.wHour,
                    systemTime.wMinute,
                    systemTime.wSecond,
                    systemTime.wMilliseconds,
                    diffTime / 10000); // Display in milliseconds

                // Set the previous time to the current time for the next report
                m_previousTime = currentTime; 
          }

          DOUBLE latitude = 0, longitude = 0, altitude = 0, errorRadius = 0, altitudeError = 0;

            // Print the Latitude
            if (SUCCEEDED(spLatLongReport->GetLatitude(&latitude)))
            {
                printf("Latitude: %f\n", latitude);
            }

            // Print the Longitude
            if (SUCCEEDED(spLatLongReport->GetLongitude(&longitude)))
            {
                printf("Longitude: %f\n", longitude);
            }

            // Print the Altitude
            if (SUCCEEDED(spLatLongReport->GetAltitude(&altitude)))
            {
                printf("Altitude: %f\n", altitude);
            }
            else
            {
                // Altitude is optional and may not be available
                printf("Altitude: Not available.\n");
            }

            // Print the Error Radius
            if (SUCCEEDED(spLatLongReport->GetErrorRadius(&errorRadius)))
            {
                printf("Error Radius: %f\n", errorRadius);
            }

            // Print the Altitude Error
            if (SUCCEEDED(spLatLongReport->GetAltitudeError(&altitudeError)))
            {
                printf("Altitude Error: %f\n", altitudeError);
            }
            else
            {
                // Altitude Error is optional and may not be available.
                printf("Altitude Error: Not available.\n");
            }
        }
    }

    return S_OK;
}

// This is called when the status of a report type changes.
// The LOCATION_REPORT_STATUS enumeration is defined in LocApi.h in the SDK
STDMETHODIMP CLocationEvents::OnStatusChanged(REFIID reportType, LOCATION_REPORT_STATUS status)
{
    if (IID_ILatLongReport == reportType)
    {
        switch (status)
        {
        case REPORT_NOT_SUPPORTED:
            wprintf(L"\nNo location sensor installed for this report type.\n");
            break;
        case REPORT_ERROR:
            wprintf(L"\nReport error.\n");
            break;
        case REPORT_ACCESS_DENIED:
            wprintf(L"\nAccess denied to reports.\n");
            break;
        case REPORT_INITIALIZING:
            wprintf(L"\nReport is initializing.\n");
            break;
        case REPORT_RUNNING:
            wprintf(L"\nRunning.\n");
            break;
        }
    }
    else if (IID_ICivicAddressReport == reportType)
    {
    }

    return S_OK;
}

This example shows how to create the callback object declared in the previous example.



// The main Location interface
CComPtr<ILocation> spLocation; 
// The callback object for location reports
CComObject<CLocationEvents>* pLocationEvents = NULL; 

// Create the Location object
hr = spLocation.CoCreateInstance(CLSID_Location); 

if (SUCCEEDED(hr))
{
    // Create the callback object
    hr = CComObject<CLocationEvents>::CreateInstance(&pLocationEvents); 
    if (NULL != pLocationEvents)
    {
        pLocationEvents->AddRef();
    }
}

After creating the callback object, to receive report events, you must call RegisterForReport to register for reports. The following code registers for both types of reports: civic address reports and latitude/longitude reports.



// The array of report types to subscribe to
IID REPORT_TYPES[] = { IID_ILatLongReport, IID_ICivicAddressReport };

// Tell the Location API that we want to register for reports 
 for (DWORD index = 0; index < ARRAYSIZE(REPORT_TYPES); index++)
 {
     hr = spLocation->RegisterForReport(pLocationEvents,
        REPORT_TYPES[index], // Report type to register for.
        0);                  // 0 means that no minimum interval 
                             // between events is specified.
 }

Related topics

Handling Provider State Changes

 

 

Community Additions

ADD
Show:
© 2014 Microsoft