简体   繁体   中英

issues with location tracking in windows phone app

Some users of my app are complaining that the tracking side does not work. I have an GPS icon at the top of the screen the flashes while the app starts the GeoCoordinateWatcher and is trying to get the current location. When this is done and is ok the icon stops flashing and a message saying Ready appears. Users are reporting that this happens but items on the screen such as speed never update. When the app saves the locations it tracked, nothing is there.

Here is the code for the tracking part. In the page load event it calls the following

    /// <summary>
    /// Starts tracking the user
    /// </summary>
    private void StartTracking()
    {
        var app = (Application.Current as App);

        // check to see if tracking is enabled by the user                    
        if (app.LocationTrackingIsEnabled)
        {               
                (new Thread(() =>
                {
                    // Create the GeoWatcher
                    var watcher = new GeoCoordinateWatcher(GeoPositionAccuracy.High) { MovementThreshold = 1 };

                    // Check to see if we have permission to use the location services of the phone
                    if (watcher.Permission == GeoPositionPermission.Granted)
                    {
                        watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(watcher_StatusChanged);

                        var status = Observable.FromEvent<GeoPositionStatusChangedEventArgs>(watcher, "StatusChanged");
                        var readys = status.Where(o => o.EventArgs.Status == GeoPositionStatus.Ready);
                        var notReadys = status.Where(o => o.EventArgs.Status != GeoPositionStatus.Ready);
                        var readyPos = from r in readys
                                       from i in Observable.Interval(TimeSpan.FromSeconds(LocationTrackInterval))
                                       .TakeUntil(notReadys)
                                       where (DateTime.Now - watcher.Position.Timestamp.DateTime) < TimeSpan.FromSeconds(12)
                                       select watcher.Position;

                        LocationSubscribe = readyPos.Subscribe(loc =>
                        {
                            if (!HasPaused)
                            {
                                this.Dispatcher.BeginInvoke(new Action(() =>
                                {
                                    // Get current speed (meters per second);
                                    if (!double.IsNaN(loc.Location.Speed))
                                        app.CurrentPos.CurrentSpeed = Math.Round(loc.Location.Speed, 2);
                                    else
                                        app.CurrentPos.CurrentSpeed = 0;

                                    // Calculate distance
                                    if (RunLocations.Count > 0)
                                        app.CurrentPos.DistanceMeters += Math.Round(new GeoCoordinate(RunLocations[RunLocations.Count - 1].Latitude,
                                            GPSLocations[GPSLocations.Count - 1].Longitude).GetDistanceTo(loc.Location), 2);

                                    // Add Location
                                    GPSLocations.Add(new GPSLocation()
                                    {
                                        Latitude = loc.Location.Latitude,
                                        Longitude = loc.Location.Longitude,
                                        Altitude = loc.Location.Altitude,
                                        Speed = app.CurrentRun.CurrentSpeed
                                    });

                                    // Get the average speed
                                    app.CurrentPos.AverageSpeed = Math.Round((from r in GPSLocations
                                                                              select r.Speed).Average(), 2);


                                    // Set last position for use later
                                    Lastlocation = loc.Location;
                                }));
                            }
                        });

                        // Try and start the watcher
                        if (!watcher.TryStart(false, TimeSpan.FromSeconds(5)))
                        {
                            this.Dispatcher.BeginInvoke(new Action(() =>
                            {
                                MessageBox.Show("There was an error trying to get your location. Tracking is not possible.");
                            }));
                        }
                    }
                    else
                    {
                        sbGpsFlash.Stop(); // stop the flashing gps symbol
                        gpsStatus.Text = "Denied";
                    }

                })).Start();                
        }
        else
        {
            sbGpsFlash.Stop(); // stop the flashing gps symbol
            gpsStatus.Text = "Disabled";
        }
    }

void watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e)
    {
         this.Dispatcher.BeginInvoke(new Action(() =>
         {
             gpsStatus.Text = e.Status.ToString();

             switch (e.Status)
             {
                 case GeoPositionStatus.Initializing:
                     gpsStatus.Text = "Locating...";
                     break;
                 case GeoPositionStatus.Disabled:
                     gpsStatus.Text = "Disabled";
                     break;
                 case GeoPositionStatus.NoData:
                     gpsStatus.Text = "No Data";
                     break;
                 case GeoPositionStatus.Ready:
                     gpsStatus.Text = "Ready";
                     break;                                     
             }

             sbGpsFlash.Stop();
         }));
    }

Can anyone see an issue with the code that may cause the problems?

在主线程上创建geocoordinatewatcher

just a side comment.

Your code is compact, but not very readable.

You do not have to create the coordinate watcher on the main thread.

I am wondering that you only subsribe to the Status Event but not to the Location chamged Event, but this is your logic and if it is fine for you, than it is fine.

The Point is the the data you want to hve displayed at the ui can only be assigned to the ui control in the thread which created the UI control, normaly this is a thread People call the "main" thread. I do not not why this is the main thread. in fact I would call it what it is, a UI thread.

So you have to pass your data in that UI thread in which your UI control was created. So éihter start the watcher on the UI thread, or use the Dispatcher of the UI thread to pass the data to it and assign the data there to the UI control.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM