Forum Xamarin.Forms

GetLocationAsync returns latitude 0 longitude 0 on UWP with no exception

jddjdd USMember ✭✭✭

I use GetLocationAsync easily with Android but cannot get it on UWP.
My app is authorized to access the computer location though.
Windows map get the correct location but not my app...
Please look at this screenshot:

This is the full code:

                try
                {
                    GeolocationRequest request = new GeolocationRequest(GeolocationAccuracy.Lowest, TimeSpan.FromSeconds(6));

                    //Xamarin.Forms.Device.BeginInvokeOnMainThread(async () =>
                    //{
                        location = await GetLocationAsync(request);
                    //});
                    if (location != null)
                    {
                        Latitude = location.Latitude;
                        Longitude = -location.Longitude;
                        PositionType = PositionType.Satellite;
                        UTC = location.Timestamp.DateTime;
                        LastKnownLatitude = Latitude;
                        LastKnownLongitude = Longitude;
                    }
                    else
                    {
                        Latitude = 0D;
                        Longitude = 0D;
                        PositionType = PositionType.Unknown;
                        UTC = DateTime.Now.ToUniversalTime();
                    }
                }
                catch (FeatureNotSupportedException fnsEx)
                {
                    Latitude = 0D;
                    Longitude = 10D;
                    PositionType = PositionType.Unknown;
                    UTC = DateTime.Now.ToUniversalTime();
                }
                catch (FeatureNotEnabledException fneEx)
                {
                    Latitude = 10D;
                    Longitude = 0D;
                    PositionType = PositionType.Unknown;
                    UTC = DateTime.Now.ToUniversalTime();
                }
                catch (PermissionException pEx)
                {
                    Latitude = 20D;
                    Longitude = 0D;
                    PositionType = PositionType.Unknown;
                    UTC = DateTime.Now.ToUniversalTime();
                }
                catch (Exception ex)
                {
                    Latitude = 0D;
                    Longitude = 20D;
                    PositionType = PositionType.Unknown;
                    UTC = DateTime.Now.ToUniversalTime();
                }
            }
            OnPropertyChanged("StrLat");
            OnPropertyChanged("StrLon");
            OnPropertyChanged("StrDateTime");
            return this;

Any idea why latitude and longitude are 0?

Tagged:

Answers

  • LeonLuLeonLu Member, Xamarin Team Xamurai

    First of all, please set the Location permission for the application. This can be done by opening the Package.appxmanifest and selecting the Capabilities tab and checking Location.

    Then, please try to use following code to make a test.

     private async void Button_Clicked_1(object sender, EventArgs e)
            {
                var request = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromSeconds(10));
                var cts = new CancellationTokenSource();
                var location = await Geolocation.GetLocationAsync(request, cts.Token);
    
                if (location != null)
                {
                  await  DisplayAlert("info", $"Latitude: {location.Latitude}, Longitude: {location.Longitude}, Altitude: {location.Altitude}","OK");
                }
    
            }
    

    Here is running GIF.

  • jddjdd USMember ✭✭✭

    Hello @LeonLu,
    Thank you for your help.
    The Location permission for the application was set.
    The issue is that when I Geolocation.GetLocationAsync(request), I get the following exception:

    Xamarin.Essentials.PermissionException: 'Permission request must be invoked on main thread.'

    So I tried to encapsulate it in a function that was doing:

    Location location;
    Xamarin.Forms.Device.BeginInvokeOnMainThread(async () =>
    {
        location = await Geolocation.GetLocationAsync(request);
    });
    return location;
    

    But then I realised that the function did not return the value it had got on the MainThread as the main thread had not joined the UI.thread (I am explaining what I understand that may not be true...)

    I get the same Xamarin.Essentials.PermissionException with the following code:

                        GeolocationRequest request = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromSeconds(3));
                        var cts = new CancellationTokenSource();
                        location = await Geolocation.GetLocationAsync(request, cts.Token);
    

    So I have to find out how to return a value to the UI.Thread from the MainThread...

  • LeonLuLeonLu Member, Xamarin Team Xamurai

    My Xamarin.Essentials version is 1.5.3.2 and Xamarin.Forms version is 4.8.0.1560, please keep the version as mine.

  • jddjdd USMember ✭✭✭

    @LeonLu Thanks very much.
    You execute:

    var cts = new CancellationTokenSource();
    

    from the code behind while I call it from a ViewModel in a Device.StartTimer. May be this is why I get an Xamarin.Essentials.PermissionException: 'Permission request must be invoked on main thread.' ??

    So I put the code in the main thread and invoked the property change in the main thread:

            private void StartPositionTimer()
            {
                Device.StartTimer(TimeSpan.FromSeconds(2), () =>
                {
                    Xamarin.Forms.Device.BeginInvokeOnMainThread(async () =>
                    {
                        try
                        {
                            GeolocationRequest request = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromSeconds(3));
                            var cts = new System.Threading.CancellationTokenSource();
                            location = await Geolocation.GetLocationAsync(request, cts.Token);
                            if (location != null)
                            {
                                CurrentPosition.Latitude = location.Latitude;
                                CurrentPosition.Longitude = -location.Longitude;
                            }
                        }
                        catch (Exception ex) {}
                        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("StrLat"));
                        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("StrLon"));
                    });
                    return pageVisible;
                });
            }
        }
    

    That works well but sometimes I get an System.Threading.Tasks.TaskCanceledException: 'A task was canceled.'
    There is no way to work around...

  • LeonLuLeonLu Member, Xamarin Team Xamurai

    If you get the System.Threading.Tasks.TaskCanceledException: 'A task was canceled.'. You can not get the location data Within 2 seconds, you can increase the second to 4 or 5 like this code TimeSpan.FromSeconds(5)

  • jddjdd USMember ✭✭✭

    ok thank you.
    Why the exception is not caught as I wrote it in a Try-Catch?

  • LeonLuLeonLu Member, Xamarin Team Xamurai

    That is odd, you can try to move the try-catch to outside the Device.StartTimer like following code, then figure out the Exception type:TimeoutException or TaskCanceledException

      try
                {
                    Device.StartTimer(TimeSpan.FromSeconds(2), () =>
                    {
                        Xamarin.Forms.Device.BeginInvokeOnMainThread(async () =>
                        {
    
                                GeolocationRequest request = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromSeconds(3));
                                var cts = new System.Threading.CancellationTokenSource();
                                var location = await Geolocation.GetLocationAsync(request, cts.Token);
                                if (location != null)
                                {
                                    CurrentPosition.Latitude = location.Latitude;
                                    CurrentPosition.Longitude = -location.Longitude;
                                }
    
    
                               PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("StrLat"));
                              PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("StrLon"));
                        });
                        return pageVisible;
                    });
                }
                catch (Exception ex)
                {
    
                    if (ex.InnerException is TimeoutException)
                    {
                        ex = ex.InnerException;
                    }
                    else if (ex is TaskCanceledException)
                    {
                        if ((ex as TaskCanceledException).CancellationToken == null || (ex as TaskCanceledException).CancellationToken.IsCancellationRequested == false)
                        {
                            ex = new TimeoutException("Timeout occurred");
                        }
                    }
                    Debug.WriteLine(string.Format("Exception at calling {0}", ex.Message), ex);
    
    
                }
    
    
    
Sign In or Register to comment.