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)); } } } }
public GeoLocationStatusChangedEventArgs(GeoLocationStatus status) { Status = status; }