位置服务返回 WP7 上以前的坐标

发布于 2024-11-14 09:15:36 字数 3510 浏览 1 评论 0原文

我使用的是官方网站中的代码,我在多个测试设备上始终看到相同的行为 - 它不是获取设备的当前位置,而是获取之前的位置(最远 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
        }

我期望发生的是在 StatusChanged 被调用且状态为 Ready 后,对 PositionChanged 进行一系列连续的调用。如果“就绪”后继续调用,我希望最终会得到正确的坐标 - 但在那之后它永远不会调用。

这种情况不会在模拟器上发生,只会在实际设备上发生(这使得测试变得非常困难 - 因为它实际上涉及每个测试之间的驱动!)

我也在运行教程中的源代码,它的作用大致相同。

谁能告诉我更多关于这里的预期行为以及我如何获得我需要的东西 - 这只是使用应用程序时设备在当前位置的一组坐标。

I'm using the code from the official site, and I am consistently seeing the same behavior on multiple test devices - instead of getting the current location of the device, it gets the previous location (up to 30 miles away, where I was an hour ago).

        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
        }

What I would expect to have happen is to get a continuous series of calls to PositionChanged after StatusChanged is called with a Status of Ready. If the calls continued after Ready, I expect I would eventually get the correct coordinates - but it never calls after that point.

This does not occur with the emulator, only on the actual device (making this extremely difficult to test - since it actually involves driving between each test!)

I am running the source code from the tutorial as well, and it does roughly the same.

Can anyone tell me more about the expected behavior here and how I get what I need - which is simply a set of coordinates for the device at the current location when the app is being used.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

等数载,海棠开 2024-11-21 09:15:36

我自己也遇到了同样的问题 - 这有两个部分。

事实证明,地理坐标观察器返回最后一个已知的正确位置 - 这几乎总是过时的。我所做的是这样的:
检查状态是否为 GeoPositionStatus.Ready,然后确保该位置的日期时间是最近的(最近 5 分钟内)。然后,您可以进一步检查 e.Position.Location.Horizo​​ntalAccuracy <= 350(因此低于 350m) - 但是通过日期时间检查执行此操作可能会导致手机需要很长时间才能获得位置越低设置精度,因此最好通过日期检查获得初始位置,然后继续尝试通过精度检查获得更好的位置。当应用程序开始获得更快的结果时,我也会立即启动观察程序。

另一个问题是 MovementThreshold。如果您按照我上面所说的操作,可能仍需要一段时间才能获得准确的位置,并且您可能会遇到您提到的间歇性问题,即它不会第二次触发(最终会触发,具体取决于您等待的时间 -这可能需要几分钟)。我发现的最好的事情是启动 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;
    }
}

I had the same problem myself - there are 2 parts to this.

Turns out the GeoCoordinateWatcher returns the last known good position - which is almost always out of date. What I do is something like this:
Check that the status is GeoPositionStatus.Ready and then ensure the datetime of the position is recent (within the last 5 mins). You can then go further and check that e.Position.Location.HorizontalAccuracy <= 350 (so under 350m) - but doing this with the datetime check as well can cause the phone to take a long time to get a position the lower you set the accuracy, so it may be best to get an initial position with the date check, and then continue to try get a better position with the Accuracy check. I also start the watcher as soon as the app starts to get faster results.

The other issue is MovementThreshold. If you do as I said above, it might still take a while before you get an accurate position, and you will likely experience the intermittent problem you mentioned where it does not fire the 2nd time (it does eventually, depending how long you wait - this can be minutes). The best thing I have found is to start the GeoCoordinateWatcher with the threshold set to 0. Once you have got an accurate position, stop the watcher, set the threshold to the actual one you want (eg 10), and then start it again. If you set this without stopping first, it will not use the new value.

<!-- 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;
    }
}
往日情怀 2024-11-21 09:15:36

看起来解决方法是阻止它使用第一个值并从第二个事件获取它:

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;

我不知道为什么,但当我附加到调试器运行时,上面的代码似乎工作得很好然后在实际使用中频繁挂起(即事件从未触发,我的 UI 似乎挂起)。在连接到调试器时我从未设法重现该问题。

更新:看起来这并不总是有效。在某些情况下,它不会第二次触发,因此我的代码永远不会完成运行。如果有人可以提供更多有关此问题的信息,让我更接近简单地获得设备的实际当前位置,我肯定会将您的答案标记为答案。谢谢!

It looks like the fix was to block it from using the first value and getting it from the second event instead:

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;
    }

I'm still baffled about why I don't get more events or why it fires an incorrect value first, but the above code seems to be working.

One note, for anyone else trying this, is that you might think getting the value in the StatusChanged event would work, like so:

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

I don't know why, but the above code seemed to work perfectly when I was running attached to the debugger and then frequently hung (that is, the event never fired and my UI seemed to hang) in practical use. I never managed to reproduced the issue while attached to the debugger.

UPDATE: It looks like this isn't working all of the time. In some cases it doesn't fire the second time and so my code never completes running. If anyone can provide more information around this that gets me closer to simply having the actual current location of the device without fail, I will definitely mark your answer as the answer. Thanks!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文