public async Task <Position> GetPositionAsync(TimeSpan?timeout = null, CancellationToken?cancelToken = null) { var timeoutMilliseconds = timeout.HasValue ? (int)timeout.Value.TotalMilliseconds : Timeout.Infinite; if (timeoutMilliseconds <= 0 && timeoutMilliseconds != Timeout.Infinite) { throw new ArgumentOutOfRangeException(nameof(timeout), "Timeout must be greater than or equal to 0"); } if (!cancelToken.HasValue) { cancelToken = CancellationToken.None; } var hasPermission = await CheckPermissionsAsync(); if (!hasPermission) { throw new GeolocationException(GeolocationError.Unauthorized); } var tcs = new TaskCompletionSource <Position>(); var providers = new List <string>(); if (ProvidersToUse == null || ProvidersToUse.Length == 0) { providers.AddRange(Providers); } else { foreach (var provider in Providers) { if (ProvidersToUse?.Contains(provider) ?? false) { continue; } providers.Add(provider); } } void SingleListenerFinishCallback() { if (_singleListener == null) { return; } for (int i = 0; i < providers.Count; ++i) { Manager.RemoveUpdates(_singleListener); } } _singleListener = new GeolocationSingleListener(Manager, (float)DesiredAccuracy, timeoutMilliseconds, providers.Where(Manager.IsProviderEnabled), finishedCallback: SingleListenerFinishCallback); if (cancelToken != CancellationToken.None) { cancelToken.Value.Register(() => { _singleListener.Cancel(); for (int i = 0; i < providers.Count; ++i) { Manager.RemoveUpdates(_singleListener); } }, true); } try { var looper = Looper.MyLooper() ?? Looper.MainLooper; int enabled = 0; for (var i = 0; i < providers.Count; ++i) { if (Manager.IsProviderEnabled(providers[i])) { enabled++; } Manager.RequestLocationUpdates(providers[i], 0, 0, _singleListener, looper); } if (enabled == 0) { for (int i = 0; i < providers.Count; ++i) { Manager.RemoveUpdates(_singleListener); } tcs.SetException(new GeolocationException(GeolocationError.PositionUnavailable)); return(await tcs.Task); } } catch (Java.Lang.SecurityException ex) { tcs.SetException(new GeolocationException(GeolocationError.Unauthorized, ex)); return(await tcs.Task); } return(await _singleListener.Task); }
/// <summary> /// Gets position async with specified parameters /// </summary> /// <param name="timeout">Timeout to wait, Default Infinite</param> /// <param name="cancelToken">Cancelation token</param> /// <param name="includeHeading">If you would like to include heading</param> /// <returns>Position</returns> public async Task <Position> GetPositionAsync(TimeSpan?timeout, CancellationToken?cancelToken = null, bool includeHeading = false) { var timeoutMilliseconds = timeout.HasValue ? (int)timeout.Value.TotalMilliseconds : Timeout.Infinite; if (timeoutMilliseconds <= 0 && timeoutMilliseconds != Timeout.Infinite) { throw new ArgumentOutOfRangeException(nameof(timeout), "timeout must be greater than or equal to 0"); } if (!cancelToken.HasValue) { cancelToken = CancellationToken.None; } var hasPermission = await CheckWhenInUsePermission(); if (!hasPermission) { throw new GeolocationException(GeolocationError.Unauthorized); } var tcs = new TaskCompletionSource <Position>(); if (!IsListening) { var providers = new List <string>(); if (ProvidersToUse == null || ProvidersToUse.Length == 0) { providers.AddRange(Providers); } else { //only add providers requested. foreach (var provider in Providers) { if (ProvidersToUse == null || !ProvidersToUse.Contains(provider)) { continue; } providers.Add(provider); } } void SingleListnerFinishCallback() { if (singleListener == null) { return; } for (var i = 0; i < providers.Count; ++i) { Manager.RemoveUpdates(singleListener); } } singleListener = new GeolocationSingleListener(Manager, (float)DesiredAccuracy, timeoutMilliseconds, providers.Where(Manager.IsProviderEnabled), finishedCallback: SingleListnerFinishCallback); if (cancelToken != CancellationToken.None) { cancelToken.Value.Register(() => { singleListener.Cancel(); for (var i = 0; i < providers.Count; ++i) { Manager.RemoveUpdates(singleListener); } }, true); } try { var looper = Looper.MyLooper() ?? Looper.MainLooper; var enabled = 0; for (var i = 0; i < providers.Count; ++i) { if (Manager.IsProviderEnabled(providers[i])) { enabled++; } Manager.RequestLocationUpdates(providers[i], 0, 0, singleListener, looper); } if (enabled == 0) { for (int i = 0; i < providers.Count; ++i) { Manager.RemoveUpdates(singleListener); } tcs.SetException(new GeolocationException(GeolocationError.PositionUnavailable)); return(await tcs.Task); } } catch (Java.Lang.SecurityException ex) { tcs.SetException(new GeolocationException(GeolocationError.Unauthorized, ex)); return(await tcs.Task); } return(await singleListener.Task); } // If we're already listening, just use the current listener lock (positionSync) { if (lastPosition == null) { if (cancelToken != CancellationToken.None) { cancelToken.Value.Register(() => tcs.TrySetCanceled()); } EventHandler <PositionEventArgs> gotPosition = null; gotPosition = (s, e) => { tcs.TrySetResult(e.Position); PositionChanged -= gotPosition; }; PositionChanged += gotPosition; } else { tcs.SetResult(lastPosition); } } return(await tcs.Task); }