Как поддерживать 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.

Другие вопросы по тегам