CLLocationManager.RequestLocation Xamarin.Forms iOS

RaphaelChiorlinRanieriRaphaelChiorlinRanieri BRMember ✭✭✭
edited August 2016 in Xamarin.Forms

Hello,

I'm using GeoLocation plugin from Xamarin Labs as Base for my own.

As I only need a single location and not to monitore anything.. I'm trying to use .RequestLocation( ) Method Instead of .StartUpdatingLocation( ) from CLLocationManager.

I'm giving it a shot because I'm having some time issues with .StartUpdatingLocation( ) since it is taking too long to return a location and apple recommends RequestLocation for just one location..

So I delegate my LocationManager to a custom CLLocationManagerDelegate

                        var m = GetManager();


                        var singleListener = new GeolocationSingleUpdateDelegate(m, DesiredAccuracy, includeHeading, timeout, cancelToken);
                        m.Delegate = singleListener;

My first problem was that I could not use the override that I was using with StartUpdatingLocation in my Delegate:

public override void UpdatedLocation(CLLocationManager manager, CLLocation newLocation, CLLocation oldLocation)

I had to implement a new override to use it:

    public override void LocationsUpdated(CLLocationManager manager, CLLocation[] locations)

However it is never returning any location.

I would like to know if it is a correct way to use RequestLocation( ) Method.

Here is my viewModel GetLocation Method that I use to call the manager:

    public async void InitLocationService()
        {



            DesiredAccuracy = 100;

            _cancelSource = new CancellationTokenSource();

            await this.GetPositionAsync(20000, _cancelSource.Token, false)
                .ContinueWith(t =>
                    {
                        _positionStatus = string.Empty;
                        //IsBusy = false;
                        if (t.IsFaulted)
                        {
                            _positionStatus = ((Xamarin.Forms.Labs.Services.Geolocation.GeolocationException) t.Exception.InnerException).Error.ToString();
                            //Cancel Operation

                        }
                        else if (t.IsCanceled)
                        {
                            _positionStatus = "Canceled";
                            //Cancel Operation

                        }
                        else
                        {
                            _positionStatus = "ok";
                            //Do Stuff

                        }
                    }, _scheduler);

                    }

Here is the GetPositionFunc

public Task<Model_Current_Location> GetPositionAsync(int timeout, CancellationToken cancelToken, bool includeHeading)
                    {
                        if (timeout <= 0 && timeout != Timeout.Infinite)
                        {
                            throw new ArgumentOutOfRangeException("timeout", "Timeout must be positive or Timeout.Infinite");
                        }

                        TaskCompletionSource<Model_Current_Location> tcs;

                        var m = GetManager();

                        tcs = new TaskCompletionSource<Model_Current_Location>(m);
                        var singleListener = new GeolocationSingleUpdateDelegate(m, DesiredAccuracy, includeHeading, timeout, cancelToken);
                        m.Delegate = singleListener;

                        //m.StartUpdatingLocation();

                        m.RequestLocation();

                        if (includeHeading && SupportsHeading)
                        {
                            m.StartUpdatingHeading();
                        }

                        return singleListener.Task;

                    }

Here is the full code of my delegate LocationsUpdate Method:

public override void LocationsUpdated(CLLocationManager manager, CLLocation[] locations)
        {
            //base.LocationsUpdated(manager, locations);

            foreach (var newLocation in locations)
            {
                if (newLocation.HorizontalAccuracy < 0)
                {
                    return;
                }

                if (_haveLocation && newLocation.HorizontalAccuracy > _position.Accuracy)
                {
                    return;
                }

                _position.Accuracy = newLocation.HorizontalAccuracy;
                _position.Altitude = newLocation.Altitude;
                _position.AltitudeAccuracy = newLocation.VerticalAccuracy;
                _position.Latitude = newLocation.Coordinate.Latitude;
                _position.Longitude = newLocation.Coordinate.Longitude;
                _position.Speed = newLocation.Speed;
                _position.Timestamp = new DateTimeOffset((DateTime)newLocation.Timestamp);

                _haveLocation = true;

                if (_position.Accuracy <= _desiredAccuracy)
                {
                    Model_Current_Location pos = new Model_Current_Location()
                    {
                        Latitude = _position.Latitude,
                        Longitude = _position.Longitude
                    };
                    _tcs.TrySetResult(pos);
                    StopListening();
                }

            }
        }

When it set the result:

_tcs.TrySetResult(pos);

It returns the position for GetPositionAsync and then the //Do Stuff is done.

Answers

Sign In or Register to comment.