Как поддерживать API геолокации Windows 8 и 8.1
Я добавил поддержку геолокации в свою программу, но у меня есть проблема, с которой я не уверен, как ее решить. Я использую VS 2012.
Я добавил в свое решение DLL, которая выполняет все вызовы геолокации. Я установил поддерживаемую версию Windows 8.1 в файле.csproj. Проект DLL также использует.NET 4.5, в то время как остальные проекты в решении используют.NET 4.0.
У меня есть следующий код в методе, который получает позицию:
protected override void Initialize() {
// Initialization code here
ParseGeoposition(); // Exception is thrown on this line
}
private void ParseGeoPositin() {
// . . .
bool done = false;
while ( !done )
try {
if ( UseCoordinate ) {
newPosition.Position.Latitude = positionRecord.Coordinate.Latitude;
newPosition.Position.Longitude = positionRecord.Coordinate.Longitude;
} else {
newPosition.Position.Latitude = positionRecord.Coordinate.Point.Position.Latitude;
newPosition.Position.Longitude = positionRecord.Coordinate.Point.Position.Longitude;
}
done = true;
} catch ( MissingMethodException ) {
if ( !UseCoordinate ) {
throw new NotSupportedException( "This machine does not support the Windows Geolocation API." );
}
UseCoordinate = false;
}
// . . .
}
UseCoordinate
флаг начинается true
, Код должен перейти на использование Point
свойство (путем установки UseCoordinate
в false
Если Coordinate
свойство не поддерживается.
Код отлично работает на моей машине для разработки Windows 8.1. Но когда я устанавливаю его на компьютер с Windows 8.0, A MissingMethodException
бросается на строку, которая вызывает метод с этим кодом. Это как если бы попытка не там. Исключение гласит:
System.MissingMethodException: метод не найден: "Windows.Devices.Geolocation.Geopoint Windows.Devices.Geolocation.Geocoordinate.get_Point()".
Очевидно, что мой подход ошибочен. Я бы предпочел не смотреть номер версии Windows, так как мой менеджер не хочет, чтобы я. Как правильно это кодировать
2 ответа
Исключение происходит, когда метод компилируется JITer - вам нужно либо использовать 8.0 совместимые вызовы API геолокации (Geolocator
и друзья), или охранные вызовы методов, которые используют специальные инструкции 8.1 с соответствующими try ... catch
блоки.
Используя информацию Роуленда, я смог заставить это работать. Разница между API-интерфейсами Windows 8 и Windows 8.1 заключается в Geocoordinate
класса Coordinate
имущество. В Windows 8 Coordinate
собственность Geocoordinate
объект, который имеет Latitude
, Longitude
, а также Altitude
свойства. В Windows 8.1 эти свойства все еще существуют, но помечены как устаревшие. Geocoordinate
класс в Windows 8.1 имеет новое свойство под названием Point
типа Geopoint
, Это свойство называется Position
типа BasicGeoposition
, Этот объект имеет Latitude
, Longitude
, а также Altitude
свойства.
Там уже была частная переменная экземпляра в классе под названием positionRecord
:
private Geoposition positionRecord = null;
Это устанавливается путем вызова GetPositionAsync
в Initialize
метод, а затем всякий раз, когда Geolocator
поднимает его PositionChanged
событие. Я создал два набора функций в своем коде:
private double GetAltitudeFromCoordinate() {
return positionRecord.Coordinate.Altitude == null ? 0.0 : positionRecord.Coordinate.Altitude.Value;
}
private double GetAltitudeFromPoint() {
return positionRecord.Coordinate.Point.Position.Altitude;
}
private double GetLatitudeFromCoordinate() {
return positionRecord.Coordinate.Latitude;
}
private double GetLatitudeFromPoint() {
return positionRecord.Coordinate.Point.Position.Latitude;
}
private double GetLongitudeFromCoordinate() {
return positionRecord.Coordinate.Longitude;
}
private double GetLongitudeFromPoint() {
return positionRecord.Coordinate.Point.Position.Longitude;
}
Затем я создал два метода, которые вызываются для анализа широты и долготы:
private void ParseLatLonFromCoordinate( GpsInformation newPosition ) {
// We assume this is a Windows 8.0 machine that doesn't have the Point property.
newPosition.Position.Latitude = positionRecord.Coordinate.Latitude;
newPosition.Position.Longitude = positionRecord.Coordinate.Longitude;
}
private void ParseLatLonFromPoint( GpsInformation newPosition ) {
// The system must not support the Coordinate.Latitude & Longitude properties any more.
newPosition.Position.Latitude = positionRecord.Coordinate.Point.Position.Latitude;
newPosition.Position.Longitude = positionRecord.Coordinate.Point.Position.Longitude;
}
Я добавил bool
свойство называется UseCoordinates
к классу. В коде инициализации программы я добавил эту строку для инициализации флага:
UseCoordinate = positionRecord.Coordinate.GetType().GetProperty( "Point" ) == null;
Наконец, я добавил метод ParsePosition
который вызывается после кода выше и всякий раз, когда Geolocator
поднимает PositionChanged
событие:
private void ParsePosition() {
GpsInformation newPosition = new GpsInformation();
newPosition.TimeStamp = DateTime.Now;
try {
if ( UseCoordinate )
ParseLatLonFromCoordinate( newPosition );
else
ParseLatLonFromPoint( newPosition );
} catch ( MissingMethodException ) {
// The Geolocation API must not be supported.
throw new NotSupportedException( "This machine does not support the Windows Geolocation API." );
}
// . . .
}
Это работает на Windows 8 и 8.1 без броска MissingMethodExceptions.