static async Task <Location> PlatformLocationAsync(GeolocationRequest request, CancellationToken cancellationToken)
        {
            await Permissions.RequireAsync(PermissionType.LocationWhenInUse);

            var locationManager = Platform.LocationManager;

            // get the best possible provider for the requested accuracy
            var provider = GetBestProvider(locationManager, request.DesiredAccuracy);

            // if no providers exist, we can't get a location
            // let's punt and try to get the last known location
            if (string.IsNullOrEmpty(provider))
            {
                return(await GetLastKnownLocationAsync());
            }

            var tcs = new TaskCompletionSource <AndroidLocation>();

            var listener = new SingleLocationListener();

            listener.LocationHandler = HandleLocation;

            cancellationToken = Utils.TimeoutToken(cancellationToken, request.Timeout);
            cancellationToken.Register(Cancel);

            // start getting location updates
            // make sure to use a thread with a looper
            var looper = Looper.MyLooper() ?? Looper.MainLooper;

            locationManager.RequestLocationUpdates(provider, 0, 0, listener, looper);

            var androidLocation = await tcs.Task;

            if (androidLocation == null)
            {
                return(null);
            }

            return(androidLocation.ToLocation());

            void HandleLocation(AndroidLocation location)
            {
                RemoveUpdates();
                tcs.TrySetResult(location);
            }

            void Cancel()
            {
                RemoveUpdates();
                tcs.TrySetResult(null);
            }

            void RemoveUpdates()
            {
                locationManager.RemoveUpdates(listener);
            }
        }
Example #2
0
        static async Task <Location> PlatformLocationAsync(GeolocationRequest request, CancellationToken cancellationToken)
        {
            if (!CLLocationManager.LocationServicesEnabled)
            {
                throw new FeatureNotEnabledException("Location services are not enabled on device.");
            }

            await Permissions.RequestAsync <Permissions.LocationWhenInUse>();

            // the location manager requires an active run loop
            // so just use the main loop
            CLLocationManager manager = null;

            NSRunLoop.Main.InvokeOnMainThread(() => manager = new CLLocationManager());

            var tcs = new TaskCompletionSource <CLLocation>(manager);

            var listener = new SingleLocationListener();

            listener.LocationHandler += HandleLocation;

            cancellationToken = Utils.TimeoutToken(cancellationToken, request.Timeout);
            cancellationToken.Register(Cancel);

            manager.DesiredAccuracy = request.PlatformDesiredAccuracy;
            manager.Delegate        = listener;

#if __IOS__
            // we're only listening for a single update
            manager.PausesLocationUpdatesAutomatically = false;
#endif

            manager.StartUpdatingLocation();

            var clLocation = await tcs.Task;

            return(clLocation?.ToLocation());

            void HandleLocation(CLLocation location)
            {
                manager.StopUpdatingLocation();
                tcs.TrySetResult(location);
            }

            void Cancel()
            {
                manager.StopUpdatingLocation();
                tcs.TrySetResult(null);
            }
        }
Example #3
0
        static async Task <Location> PlatformLocationAsync(GeolocationRequest request, CancellationToken cancellationToken)
        {
            await Permissions.RequireAsync(PermissionType.LocationWhenInUse);

            // the location manager requires an active run loop
            // so just use the main loop
            CLLocationManager manager = null;

            NSRunLoop.Main.InvokeOnMainThread(() => manager = new CLLocationManager());

            var tcs = new TaskCompletionSource <CLLocation>(manager);

            var listener = new SingleLocationListener();

            listener.LocationHandler += HandleLocation;

            cancellationToken = Utils.TimeoutToken(cancellationToken, request.Timeout);
            cancellationToken.Register(Cancel);

            manager.DesiredAccuracy = request.PlatformDesiredAccuracy;
            manager.Delegate        = listener;

            // we're only listening for a single update
            manager.PausesLocationUpdatesAutomatically = false;

            manager.StartUpdatingLocation();

            var clLocation = await tcs.Task;

            if (clLocation == null)
            {
                return(null);
            }

            return(clLocation.ToLocation());

            void HandleLocation(CLLocation location)
            {
                manager.StopUpdatingLocation();
                tcs.TrySetResult(location);
            }

            void Cancel()
            {
                manager.StopUpdatingLocation();
                tcs.TrySetResult(null);
            }
        }
        static async Task <Location> PlatformLocationAsync(GeolocationRequest request, CancellationToken cancellationToken)
        {
            await Permissions.RequestAsync <Permissions.LocationWhenInUse>();

            var locationManager = Platform.LocationManager;

            var enabledProviders = locationManager.GetProviders(true);
            var hasProviders     = enabledProviders.Any(p => !ignoredProviders.Contains(p));

            if (!hasProviders)
            {
                throw new FeatureNotEnabledException("Location services are not enabled on device.");
            }

            // get the best possible provider for the requested accuracy
            var providerInfo = GetBestProvider(locationManager, request.DesiredAccuracy);

            // if no providers exist, we can't get a location
            // let's punt and try to get the last known location
            if (string.IsNullOrEmpty(providerInfo.Provider))
            {
                return(await GetLastKnownLocationAsync());
            }

            var tcs = new TaskCompletionSource <AndroidLocation>();

            var allProviders = locationManager.GetProviders(false);

            var providers = new List <string>();

            if (allProviders.Contains(LocationManager.GpsProvider))
            {
                providers.Add(LocationManager.GpsProvider);
            }
            if (allProviders.Contains(LocationManager.NetworkProvider))
            {
                providers.Add(LocationManager.NetworkProvider);
            }

            if (providers.Count == 0)
            {
                providers.Add(providerInfo.Provider);
            }

            var listener = new SingleLocationListener(locationManager, providerInfo.Accuracy, providers);

            listener.LocationHandler = HandleLocation;

            cancellationToken = Utils.TimeoutToken(cancellationToken, request.Timeout);
            cancellationToken.Register(Cancel);

            // start getting location updates
            // make sure to use a thread with a looper
            var looper = Looper.MyLooper() ?? Looper.MainLooper;

            foreach (var provider in providers)
            {
                locationManager.RequestLocationUpdates(provider, 0, 0, listener, looper);
            }

            var androidLocation = await tcs.Task;

            if (androidLocation == null)
            {
                return(null);
            }

            return(androidLocation.ToLocation());

            void HandleLocation(AndroidLocation location)
            {
                RemoveUpdates();
                tcs.TrySetResult(location);
            }

            void Cancel()
            {
                RemoveUpdates();
                tcs.TrySetResult(listener.BestLocation);
            }

            void RemoveUpdates()
            {
                for (var i = 0; i < providers.Count; i++)
                {
                    locationManager.RemoveUpdates(listener);
                }
            }
        }