private void HandleLocationStatusChangedEvent(ReportStatus newStatus)
        {
            //
            // If we are registered for civic address reports and a latlong provider
            // has become available, then unregister for civic address reports
            //
            if (m_civicAddrRegistered && m_latLongStatus != ReportStatus.NotSupported)
            {
                if (m_civicAddrRegistered)
                {
                    Guid reportType = LocationReportKey.CivicAddressReport;
                    if (m_location.UnregisterForReport(ref reportType) == 0)
                    {
                        m_civicAddrRegistered = false;
                    }
                }
            }

            GeoLocationStatus prevStatus = Status;
            //
            // Update the current status
            //
            ReportStatus status = (ReportStatus.NotSupported != m_latLongStatus) ? m_latLongStatus : m_civicAddrStatus;

            m_curStatus = m_geoStatusMap[(int)status];

            //
            // If the reported status has changed, send a status change event
            //
            if (prevStatus != Status)
            {
                OnStatusChanged(new GeoLocationStatusChangedEventArgs(Status));

                //
                // If we have location data and have held off sending it until the
                // status becomes ready, send the location event now
                //
                if (GeoLocationStatus.Ready == Status && m_eventPending)
                {
                    m_eventPending = false;
                    OnLocationChanged(new GeoLocationChangedEventArgs(m_curLocation));
                }

                //
                // If switching to ready from a permission denied state, then the sensor may not
                // send a location changed event. So start a worker thread to get it via a
                // synchronous request for current data.
                // (Note: Check m_curStatus rather than Status because Status won't be Ready
                // if there is no location data.)
                //
                if (prevStatus == GeoLocationStatus.NoPermissions && m_curStatus == GeoLocationStatus.Ready)
                {
                    ThreadPool.QueueUserWorkItem(new WaitCallback(this.GetLocationData), null);
                }
            }
        }
        /// <summary>
        /// Thread pool callback used to ensure location COM API is instantiated from
        /// multi-thread apartment, and register for location events.
        /// </summary>
        /// <param name="state"></param>
        private void CreateHandler(object state)
        {
            lock (this.InternalSyncObject)
            {
                try
                {
                    m_location = new COMLocation();
                }
                catch (COMException)
                {
                    Utility.Trace("Failed to CoCreate ILocation COM object.");
                }

                if (null != m_location)
                {
                    Utility.Trace("Done creating ILocation COM object");

                    //
                    // Mapping to platform accuracy
                    //
                    GeoLocationAccuracy desiredAccuracy = (GeoLocationAccuracy)state;
                    DesiredAccuracy     accuracy        = (desiredAccuracy == GeoLocationAccuracy.Low) ?
                                                          DesiredAccuracy.DefaultAccuracy : DesiredAccuracy.HighAccuracy;

                    Guid reportKey = LocationReportKey.LatLongReport;
                    m_location.SetDesiredAccuracy(ref reportKey, accuracy);

                    //
                    // Always listen for latlong reports
                    //
                    if (m_location.RegisterForReport(this, ref reportKey, 0) == 0)
                    {
                        m_latLongRegistered = true;
                    }

                    //
                    // Check the latlong status. If latlong reports are not supported, then register
                    // for civic address reports.
                    //
                    m_location.GetReportStatus(ref reportKey, ref m_latLongStatus);

                    if (ReportStatus.NotSupported == m_latLongStatus)
                    {
                        reportKey = LocationReportKey.CivicAddressReport;
                        if (m_location.RegisterForReport(this, ref reportKey, 0) == 0)
                        {
                            m_civicAddrRegistered = true;
                            m_location.GetReportStatus(ref reportKey, ref m_civicAddrStatus);
                        }
                    }
                    //
                    // set the current status to the available report type status
                    //
                    ReportStatus status = (ReportStatus.NotSupported != m_latLongStatus) ? m_latLongStatus : m_civicAddrStatus;
                    m_curStatus = m_geoStatusMap[(int)status];
                }

                Utility.DebugAssert(m_eventCreateDone != null, "m_eventCreateDone is null");

                ManualResetEvent eventDone = m_eventCreateDone;
                if (eventDone != null)
                {
                    eventDone.Set();
                }
            }
        }
        private void HandleLocationChangedEvent(ILocationReport locationReport)
        {
            const double KnotsToMetersPerSec = 463.0 / 900.0;

            GeoCoordinate coordinate = GeoCoordinate.Unknown;
            CivicAddress  address    = CivicAddress.Unknown;

            //
            // If we are listening for latlong reports and this is one,
            // extract the coordinate properties
            //
            if (m_latLongStatus != ReportStatus.NotSupported)
            {
                ILatLongReport latLongReport = locationReport as ILatLongReport;
                if (latLongReport != null)
                {
                    double latitude, longitude, errorRadius, altitude, altitudeError;
                    if ((latLongReport.GetLatitude(out latitude) == 0) &&
                        (latLongReport.GetLongitude(out longitude) == 0))
                    {
                        latLongReport.GetErrorRadius(out errorRadius);
                        latLongReport.GetAltitude(out altitude);
                        latLongReport.GetAltitudeError(out altitudeError);

                        coordinate = new GeoCoordinate(latitude, longitude, errorRadius, altitude, altitudeError);
                    }
                }
            }

            //
            // Now see if there is civic address data in the report. We do this for both latlong and civic address
            // reports to handle the case of one sensor providing both types of data. Only generate a report if
            // countryRegion and at least one other string is present. For Win 7 a country string is always present
            // because the native location provider API defaults to UserGeoID if no sensor provides one.
            //
            string countryRegion = GetStringProperty(locationReport, LocationPropertyKey.CountryRegion);

            if (countryRegion != String.Empty)
            {
                string address1      = GetStringProperty(locationReport, LocationPropertyKey.AddressLine1);
                string address2      = GetStringProperty(locationReport, LocationPropertyKey.AddressLine2);
                string city          = GetStringProperty(locationReport, LocationPropertyKey.City);
                string postalCode    = GetStringProperty(locationReport, LocationPropertyKey.PostalCode);
                string stateProvince = GetStringProperty(locationReport, LocationPropertyKey.StateProvince);

                if (address1 != String.Empty || address2 != String.Empty || city != String.Empty ||
                    postalCode != String.Empty || stateProvince != String.Empty)
                {
                    address = new CivicAddress(address1, address2, String.Empty, city, countryRegion, String.Empty, postalCode, stateProvince);
                }
            }

            //
            // if we have either coordinate or civic address report data, continue the processing
            //
            if (coordinate != GeoCoordinate.Unknown || address != CivicAddress.Unknown)
            {
                double heading = GetDoubleProperty(locationReport, LocationPropertyKey.Heading);
                double speed   = GetDoubleProperty(locationReport, LocationPropertyKey.Speed) * KnotsToMetersPerSec;

                DateTimeOffset timestamp = DateTimeOffset.Now;
                SYSTEMTIME     systime;
                if (0 == locationReport.GetTimestamp(out systime))
                {
                    timestamp = new DateTimeOffset(systime.wYear, systime.wMonth, systime.wDay, systime.wHour,
                                                   systime.wMinute, systime.wSecond, systime.wMilliseconds, TimeSpan.Zero);
                }

                GeoLocationStatus prevStatus = Status;

                m_curLocation = new GeoLocation(coordinate, heading, speed, address, timestamp);

                if (m_started)
                {
                    //
                    // Send a location change event if we are reporting a ready status. Otherwise, set
                    // an event pending flag which will cause the event to be sent when the status
                    // does switch to ready.
                    //
                    if (GeoLocationStatus.Ready == Status)
                    {
                        //
                        // The reported status may have changed because of the received data. If it
                        // has then generate a status change event.
                        //
                        if (Status != prevStatus)
                        {
                            OnStatusChanged(new GeoLocationStatusChangedEventArgs(m_curStatus));
                        }

                        OnLocationChanged(new GeoLocationChangedEventArgs(m_curLocation));
                    }
                    else
                    {
                        m_eventPending = true;
                    }
                }
                else
                {
                    //
                    // Fire Ready event when location is available in case Start() hasn't been called
                    //
                    if (GeoLocationStatus.Ready == m_curStatus)
                    {
                        OnStatusChanged(new GeoLocationStatusChangedEventArgs(m_curStatus));
                    }
                }
            }
        }
Exemplo n.º 4
0
 public GeoLocationStatusChangedEventArgs(GeoLocationStatus status)
 {
     Status = status;
 }