Search code examples
androidlocationxamarinxamarin.forms

Xamarin.Forms DependencyService difficulty getting location


So after finally getting my head around Xamarin.Forms DependencyService I have nearly got it returning the device's current location.

my interface

public interface ICurrentLocation
{
    MyLocation SetCurrentLocation();
}

MyLocation

public class MyLocation
{
    public double Latitude {get; set;}
    public double Longitude{get; set;}
}

the line that calls it

MyLocation location = DependencyService.Get<ICurrentLocation>().SetCurrentLocation();

and in the CurrentLocation class in the Android project that implements the Geolocation class of Xamarin.Mobile

[assembly: Dependency(typeof(CurrentLocation))]
namespace MyCockburn.Droid
{

    public class CurrentLocation : Activity, ICurrentLocation

        Geolocator locator;
        Position position = new Position();
        MyLocation location;

        public MyLocation SetCurrentLocation()
        {
            GetPosition();
            location = new MyLocation()
            {
                Latitude = position.Latitude,
                Longitude = position.Longitude
            };


            return location;
       }

       async void GetPosition()
       {
           try
           {
                 locator = new Geolocator(this) { DesiredAccuracy = 50 };
                 if (locator.IsListening != true)
                       locator.StartListening(minTime: 1000, minDistance: 0);

                 position = await locator.GetPositionAsync(timeout: 20000);

           }
           catch (Exception e)
           {
               Log.Debug("GeolocatorError", e.ToString());
           }
       }
   }

my problem seems to be that is returning location before position holds the longitude and latitude

I am hoping my mistake is glaringly obvious

EDIT: the code works if I run it as a normal Android Activity


Solution

  • I would do a slight modification since best practice is to either do all async or none. When you try to return the result from an async method from a non async method you can run into problems with deadlocks. Also, since you aren't using the await keyword when calling the GetPosition method, you are getting back a Task, but aren't checking when the operation is complete. I suggest slightly modifying your code as such.

    public interface ICurrentLocation {
        Task<MyLocation> GetCurrentLocation();
    }
    
    public async Task<MyLocation> GetCurrentLocation()
    {
        var position = await GetPosition();
        return new MyLocation()
        {
            Latitude = position.Latitude,
            Longitude = position.Longitude
        };
    }
    
    async Task<Location> GetPosition()
    {
        try
        {
              locator = new Geolocator(this) { DesiredAccuracy = 50 };
              if (locator.IsListening != true)
                    locator.StartListening(minTime: 1000, minDistance: 0);
    
              return await locator.GetPositionAsync(timeout: 20000);
    
        }
        catch (Exception e)
        {
            Log.Debug("GeolocatorError", e.ToString());
        }
    }