David Shochet
David Shochet

Reputation: 5375

Geolocation.GetLocationAsync is not working

I have a Xamarin.Forms application that supports UWP, iOS, and Android. Specifically, I am now testing my app on Android emulator. For getting location, I am using Xamarin.Essentials. Here are pieces of my code:

In a PageModel:

                    bu = await GeolocationSrvc.GetBusinessUnitAsync();

And here is the implementation of the method above:

    public static async Task<BusinessUnits> GetBusinessUnitAsync()
    {
        BusinessUnits bu = BusinessUnits.Aus;

        try
        {
            Location location = await GetLocation().ConfigureAwait(false);

            IEnumerable<Placemark> placemarks = await Geocoding.GetPlacemarksAsync(location);
            Placemark placemark = placemarks?.FirstOrDefault();
            string countryCode = placemark?.CountryCode;

            switch (countryCode)
            {
                case "AQ":
                case "AU":
                case "NZ":
                    bu = BusinessUnits.Aus;
                    break;
                default:
                    bu = BusinessUnits.NA;
                    break;
            }
        }
        catch (Exception)
        {
            throw;
        }

        return bu;
    }

    private static Task<Location> GetLocation()
    {
        GeolocationRequest request = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromSeconds(10));
        TaskCompletionSource<Location> locationTaskCompletionSource = new TaskCompletionSource<Location>();

        Device.BeginInvokeOnMainThread(async () =>
        {
            locationTaskCompletionSource.SetResult(await Geolocation.GetLocationAsync(request));
        });

        return locationTaskCompletionSource.Task;
    }

When the execution comes to

locationTaskCompletionSource.SetResult(await Geolocation.GetLocationAsync(request));

I am asked if I want to allow the app to get my location. If I press Yes, it works as expected. But if I press No, the location is never returned (not even null), the following code is never executed. I expected in case of answering No to use default value set in

BusinessUnits bu = BusinessUnits.Aus;

But it does not happen.

Upvotes: 0

Views: 3159

Answers (2)

Rajesh Sonar
Rajesh Sonar

Reputation: 289

Alternate approach would be to check for location permission before hand using a simple dependency service for each platform.

If the permission is granted, then continue with location fetch. Else prompt user to get permission.

For ex. Android implementation to check location permission:

public bool IsLocationPermissionGranted()
{
    if (ContextCompat.CheckSelfPermission(Application.Context, 
    Manifest.Permission.AccessFineLocation) == Permission.Granted)
    {
        return true;
    }
    return false;
}

Upvotes: 1

Roubachof
Roubachof

Reputation: 3401

You're not setting the Exception of your TaskCompletionSource object:

private static Task<Location> GetLocation()
{
    GeolocationRequest request = new GeolocationRequest(GeolocationAccuracy.Medium, TimeSpan.FromSeconds(10));
    TaskCompletionSource<Location> locationTaskCompletionSource = new TaskCompletionSource<Location>();

    Device.BeginInvokeOnMainThread(async () =>
    {
        try
        {
            locationTaskCompletionSource.SetResult(await Geolocation.GetLocationAsync(request));
        }
        catch(Exception exception)
        {
            locationTaskCompletionSource.SetException(exception);
            locationTaskCompletionSource.SetResult(null);
        }
    });

    return locationTaskCompletionSource.Task;
}

Upvotes: 2

Related Questions