Служба определения местоположения, возвращающая предыдущие координаты на WP7 - PullRequest
2 голосов
/ 06 июня 2011

Я использую код с официального сайта , и я постоянно наблюдаю одно и то же поведение на нескольких тестовых устройствах - вместо получения текущего местоположения устройства, оно получает предыдущее местоположение (вверхдо 30 миль, где я был час назад).

        private void setupMaps()
        {
            watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High);
            watcher.MovementThreshold = 10.0f;

            watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(watcher_statusChanged);
            watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(watcher_PositionChanged);

            new Thread(startLocServInBackground).Start();
        }

        void startLocServInBackground()
        {
            watcher.TryStart(true, TimeSpan.FromSeconds(60));
        }

        void watcher_statusChanged(object sender, GeoPositionStatusChangedEventArgs e)
        {
            switch (e.Status)
            {
                case GeoPositionStatus.Disabled:
                    // The Location Service is disabled or unsupported.
                    // Check to see if the user has disabled the location service.
                    if (watcher.Permission == GeoPositionPermission.Denied)
                    {
                        // the user has disabled LocServ on their device.
                        showMessage("Location is required but it is disabled. Turn it on in Settings");
                    }
                    else
                    {
                        showMessage("Location is not functioning on this phone. Sorry, Crux cannot run");
                    }
                    break;

                case GeoPositionStatus.Initializing:
                    // The location service is initializing.
                    LoadingInfo.Text = "finding location";
                    break;

                case GeoPositionStatus.NoData:
                    // The Location Service is working, but it cannot get location data
                    // due to poor signal fidelity (most likely)

                    // this fired intermittently when data was coming back :/
                    //MessageBox.Show("Location data is not available.");

                    break;

                case GeoPositionStatus.Ready:
                    // The location service is working and is receiving location data.
                    //statusTextBlock.Text = "Location data is available.";
                    LoadingInfo.Text = "Location found";
                    // THIS FIRES AFTER POSITION CHANGED HAS STOPPED FIRING
                    break;
            }
        }

        private void initPostPanel()
        {
            PostPanel.Visibility = Visibility.Visible;
        }

        void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
        {
            // update the textblock readouts.
            latitude = e.Position.Location.Latitude.ToString("0.0000000000");
            longitude = e.Position.Location.Longitude.ToString("0.0000000000");
            // THIS FIRES TWICE, BEFORE STATUS IS FIRED AS READY. THEN THIS DOESN'T CALL AGAIN
        }

Что я мог бы ожидать, так это получить непрерывную серию вызовов в PositionChanged после вызова StatusChanged с состоянием готовности.Если вызовы продолжаются после Ready, я ожидаю, что в конечном итоге получу правильные координаты - но после этой точки он никогда не будет вызывать.

Это не происходит с эмулятором, только на реальном устройстве (что делает это чрезвычайно трудным дляtest - так как он фактически включает вождение между каждым тестом!)

Я также запускаю исходный код из учебника, и он примерно такой же.

Может кто-нибудь рассказать мне больше оожидаемое поведение здесь и то, как я получаю то, что мне нужно - это просто набор координат для устройства в текущем местоположении, когда приложение используется.

Ответы [ 2 ]

2 голосов
/ 28 июня 2011

У меня была та же самая проблема - здесь есть 2 части.

Оказывается, GeoCoordinateWatcher возвращает последнюю известную хорошую позицию, которая почти всегда устарела.Что я делаю, это что-то вроде этого: проверьте, что статус GeoPositionStatus.Ready, а затем убедитесь, что дата-время позиции является недавним (в течение последних 5 минут).Затем вы можете пойти дальше и проверить, что e.Position.Location.HorizontAccuracy <= 350 (так, например, до 350 м), но выполнение этого с проверкой даты и времени также может привести к тому, что телефону понадобится много времени, чтобы занять позицию ниже установленного вами уровня.точность, поэтому может быть лучше получить начальную позицию с проверкой даты, а затем продолжить пытаться получить лучшую позицию с проверкой точности.Я также запускаю наблюдателя, как только приложение начинает получать более быстрые результаты. </p>

Другая проблема - MovementThreshold.Если вы сделаете, как я сказал выше, может пройти некоторое время, прежде чем вы получите точную позицию, и вы, вероятно, столкнетесь с периодически возникающей проблемой, о которой вы упомянули, когда она не срабатывает 2-й раз (в конечном итоге, в зависимости от того, как долго вы ждете -это могут быть минуты).Лучшее, что я нашел, - это запустить GeoCoordinateWatcher с пороговым значением, равным 0. После того, как вы получите точное положение, остановите наблюдатель, установите пороговое значение на желаемое (например, 10), а затем запустите его снова.Если вы установите этот параметр без остановки, он не будет использовать новое значение.

<!-- language: c# -->
GeoPositionStatus = CurrentGeoDeviceStatus;
    static void geoCoordWatcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
    {
        CurrentGeoDeviceStatus = e.Status;
    }
void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
    if (gpsReady && e.Position.Timestamp.DateTime.AddMinutes(5) > DateTime.Now)
    {
        latitude = e.Position.Location.Latitude.ToString("0.0000000000");
        longitude = e.Position.Location.Longitude.ToString("0.0000000000");
        locReady = true;
    }
}
0 голосов
/ 08 июня 2011

Похоже, исправление было заблокировать использование первого значения и получение его из второго события:

bool gpsReady = false;
void watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e)
{
    if (gpsReady)
    {
        latitude = e.Position.Location.Latitude.ToString("0.0000000000");
        longitude = e.Position.Location.Longitude.ToString("0.0000000000");
        locReady = true;
    }
        gpsReady = true;
    }

Я все еще не понимаю, почему я не получаю больше событий илипочему сначала запускается неверное значение, но приведенный выше код, похоже, работает.

Одно замечание для всех, кто пытается это сделать, - вы можете подумать, что получение значения в событии StatusChanged будет работать, например, так:

case GeoPositionStatus.Ready:
    latitude = watcher.Position.Location.Latitude.ToString("0.0000000000");
    longitude = watcher.Position.Location.Longitude.ToString("0.0000000000");
    break;

Я не знаю почему, но вышеприведенный код, кажется, работал идеально, когда я работал, подключенный к отладчику, а затем часто зависал (то есть событие не срабатывало, и мой пользовательский интерфейс, казалось, завис) в практическом использовании.Мне никогда не удавалось воспроизвести проблему, пока она была подключена к отладчику.

ОБНОВЛЕНИЕ: похоже, это не всегда работает.В некоторых случаях он не срабатывает во второй раз, и поэтому мой код никогда не завершает работу.Если кто-то может предоставить дополнительную информацию об этом, которая поможет мне приблизиться к простому фактическому текущему местоположению устройства, я обязательно отмечу ваш ответ как ответ.Спасибо!

...