Beispiel #1
0
        public async Task <Location> GetLocationAsync(GeolocationRequest request, CancellationToken cancellationToken)
        {
            _ = request ?? throw new ArgumentNullException(nameof(request));

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

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

            // the location manager requires an active run loop
            // so just use the main loop
            var manager = MainThread.InvokeOnMainThread(() => 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);
            }
        }
Beispiel #2
0
        public async Task <Location?> GetLocationAsync(GeolocationRequest request, CancellationToken cancellationToken)
        {
            _ = request ?? throw new ArgumentNullException(nameof(request));

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

            var geolocator = new Geolocator
            {
                DesiredAccuracyInMeters = request.PlatformDesiredAccuracy
            };

            CheckStatus(geolocator.LocationStatus);

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

            var location = await geolocator.GetGeopositionAsync().AsTask(cancellationToken);

            return(location?.Coordinate?.ToLocation());
Beispiel #3
0
 public static Task <Location?> GetLocationAsync(this IGeolocation geolocation, GeolocationRequest request) =>
 geolocation.GetLocationAsync(request ?? new GeolocationRequest(), default);
Beispiel #4
0
 public static Task <Location?> GetLocationAsync(GeolocationRequest request, CancellationToken cancelToken) =>
 Current.GetLocationAsync(request, cancelToken);
Beispiel #5
0
 public static Task <Location?> GetLocationAsync(GeolocationRequest request) =>
 Current.GetLocationAsync(request);
Beispiel #6
0
        public async Task <Location> GetLocationAsync(GeolocationRequest request, CancellationToken cancellationToken)
        {
            _ = request ?? throw new ArgumentNullException(nameof(request));

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

            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(Android.Locations.LocationManager.GpsProvider))
            {
                providers.Add(Android.Locations.LocationManager.GpsProvider);
            }
            if (allProviders.Contains(Android.Locations.LocationManager.NetworkProvider))
            {
                providers.Add(Android.Locations.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);
                }
            }
        }
Beispiel #7
0
        public async Task <Location> GetLocationAsync(GeolocationRequest request, CancellationToken cancellationToken)
        {
            _ = request ?? throw new ArgumentNullException(nameof(request));

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

            Locator service = null;
            var     gps     = Platform.GetFeatureInfo <bool>("location.gps");
            var     wps     = Platform.GetFeatureInfo <bool>("location.wps");

            if (gps)
            {
                if (wps)
                {
                    service = new Locator(LocationType.Hybrid);
                }
                else
                {
                    service = new Locator(LocationType.Gps);
                }
            }
            else
            {
                if (wps)
                {
                    service = new Locator(LocationType.Wps);
                }
                else
                {
                    service = new Locator(LocationType.Passive);
                }
            }

            var tcs = new TaskCompletionSource <bool>();

            cancellationToken = Utils.TimeoutToken(cancellationToken, request.Timeout);
            cancellationToken.Register(() =>
            {
                service?.Stop();
                tcs.TrySetResult(false);
            });

            double KmToMetersPerSecond(double km) => km * 0.277778;

            service.LocationChanged += (s, e) =>
            {
                if (e.Location != null)
                {
                    lastKnownLocation.Accuracy  = e.Location.Accuracy;
                    lastKnownLocation.Altitude  = e.Location.Altitude;
                    lastKnownLocation.Course    = e.Location.Direction;
                    lastKnownLocation.Latitude  = e.Location.Latitude;
                    lastKnownLocation.Longitude = e.Location.Longitude;
                    lastKnownLocation.Speed     = KmToMetersPerSecond(e.Location.Speed);
                    lastKnownLocation.Timestamp = e.Location.Timestamp;
                }
                service?.Stop();
                tcs.TrySetResult(true);
            };
            service.Start();

            await tcs.Task;

            return(lastKnownLocation);
        }
 public Task <Location> GetLocationAsync(GeolocationRequest request, CancellationToken cancellationToken) =>
 throw ExceptionUtils.NotSupportedOrImplementedException;
Beispiel #9
0
        public async Task <Location> GetLocationAsync(GeolocationRequest request, CancellationToken cancellationToken)
        {
            _ = request ?? throw new ArgumentNullException(nameof(request));

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

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

            // the location manager requires an active run loop
            // so just use the main loop
            var manager = MainThread.InvokeOnMainThread(() => 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
#pragma warning disable CA1416 // https://github.com/xamarin/xamarin-macios/issues/14619
            manager.PausesLocationUpdatesAutomatically = false;
#pragma warning restore CA1416
#endif

            manager.StartUpdatingLocation();

            var reducedAccuracy = false;
#if __IOS__
            if (OperatingSystem.IsIOSVersionAtLeast(14, 0))
            {
                if (request.RequestFullAccuracy && manager.AccuracyAuthorization == CLAccuracyAuthorization.ReducedAccuracy)
                {
                    await manager.RequestTemporaryFullAccuracyAuthorizationAsync("TemporaryFullAccuracyUsageDescription");
                }

                reducedAccuracy = manager.AccuracyAuthorization == CLAccuracyAuthorization.ReducedAccuracy;
            }
#endif

            var clLocation = await tcs.Task;

            return(clLocation?.ToLocation(reducedAccuracy));

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

            void Cancel()
            {
                manager.StopUpdatingLocation();
                tcs.TrySetResult(null);
            }
        }