UWP location service added.
This commit is contained in:
parent
41398ab03a
commit
d2bd5a55ec
@ -0,0 +1,33 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace eShopOnContainers.Windows.Helpers
|
||||
{
|
||||
internal class Timeout
|
||||
{
|
||||
public const int Infinite = -1;
|
||||
readonly CancellationTokenSource _canceller = new CancellationTokenSource();
|
||||
|
||||
public Timeout(int timeout, Action timesUp)
|
||||
{
|
||||
if (timeout == Infinite)
|
||||
return;
|
||||
if (timeout < 0)
|
||||
throw new ArgumentOutOfRangeException("timeoutMilliseconds");
|
||||
if (timesUp == null)
|
||||
throw new ArgumentNullException("timesUp");
|
||||
|
||||
Task.Delay(TimeSpan.FromMilliseconds(timeout), _canceller.Token).ContinueWith(t =>
|
||||
{
|
||||
if (!t.IsCanceled)
|
||||
timesUp();
|
||||
});
|
||||
}
|
||||
|
||||
public void Cancel()
|
||||
{
|
||||
_canceller.Cancel();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,166 @@
|
||||
using eShopOnContainers.Core.Models.Location;
|
||||
using eShopOnContainers.Core.Services.Location;
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.Devices.Geolocation;
|
||||
using Windows.Foundation;
|
||||
|
||||
[assembly: Xamarin.Forms.Dependency(typeof(ILocationServiceImplementation))]
|
||||
namespace eShopOnContainers.Windows.Services
|
||||
{
|
||||
public class LocationServiceImplementation : ILocationServiceImplementation
|
||||
{
|
||||
double _desiredAccuracy;
|
||||
Geolocator _locator = new Geolocator();
|
||||
|
||||
public LocationServiceImplementation()
|
||||
{
|
||||
DesiredAccuracy = 100;
|
||||
}
|
||||
|
||||
#region Internal Implementation
|
||||
|
||||
Geolocator GetGeolocator()
|
||||
{
|
||||
var loc = _locator;
|
||||
if (loc == null)
|
||||
{
|
||||
_locator = new Geolocator();
|
||||
_locator.StatusChanged += OnLocatorStatusChanged;
|
||||
loc = _locator;
|
||||
}
|
||||
return loc;
|
||||
}
|
||||
|
||||
PositionStatus GetGeolocatorStatus()
|
||||
{
|
||||
var loc = GetGeolocator();
|
||||
return loc.LocationStatus;
|
||||
}
|
||||
|
||||
static Position GetPosition(Geoposition position)
|
||||
{
|
||||
var pos = new Position
|
||||
{
|
||||
Accuracy = position.Coordinate.Accuracy,
|
||||
Altitude = position.Coordinate.Point.Position.Altitude,
|
||||
Latitude = position.Coordinate.Point.Position.Latitude,
|
||||
Longitude = position.Coordinate.Point.Position.Longitude,
|
||||
Timestamp = position.Coordinate.Timestamp.ToUniversalTime()
|
||||
};
|
||||
|
||||
if (position.Coordinate.Heading != null)
|
||||
pos.Heading = position.Coordinate.Heading.Value;
|
||||
if (position.Coordinate.Speed != null)
|
||||
pos.Speed = position.Coordinate.Speed.Value;
|
||||
if (position.Coordinate.AltitudeAccuracy.HasValue)
|
||||
pos.AltitudeAccuracy = position.Coordinate.AltitudeAccuracy.Value;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
async void OnLocatorStatusChanged(Geolocator sender, StatusChangedEventArgs e)
|
||||
{
|
||||
GeolocationError error;
|
||||
|
||||
switch (e.Status)
|
||||
{
|
||||
case PositionStatus.Disabled:
|
||||
error = GeolocationError.Unauthorized;
|
||||
break;
|
||||
case PositionStatus.NoData:
|
||||
error = GeolocationError.PositionUnavailable;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
_locator = null;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ILocationServiceImplementation
|
||||
|
||||
public double DesiredAccuracy
|
||||
{
|
||||
get { return _desiredAccuracy; }
|
||||
set
|
||||
{
|
||||
_desiredAccuracy = value;
|
||||
GetGeolocator().DesiredAccuracy = (value < 100) ? PositionAccuracy.High : PositionAccuracy.Default;
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler<PositionErrorEventArgs> PositionError;
|
||||
public event EventHandler<PositionEventArgs> PositionChanged;
|
||||
|
||||
public bool IsGeolocationAvailable
|
||||
{
|
||||
get
|
||||
{
|
||||
var status = GetGeolocatorStatus();
|
||||
while (status == PositionStatus.Initializing)
|
||||
{
|
||||
Task.Delay(10).Wait();
|
||||
status = GetGeolocatorStatus();
|
||||
}
|
||||
return status != PositionStatus.NotAvailable;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsGeolocationEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
var status = GetGeolocatorStatus();
|
||||
while (status == PositionStatus.Initializing)
|
||||
{
|
||||
Task.Delay(10).Wait();
|
||||
status = GetGeolocatorStatus();
|
||||
}
|
||||
return status != PositionStatus.Disabled && status != PositionStatus.NotAvailable;
|
||||
}
|
||||
}
|
||||
|
||||
public Task<Position> GetPositionAsync(TimeSpan? timeout = null, CancellationToken? cancelToken = null, bool includeHeading = false)
|
||||
{
|
||||
var timeoutMilliseconds = timeout.HasValue ? (int)timeout.Value.TotalMilliseconds : eShopOnContainers.Windows.Helpers.Timeout.Infinite;
|
||||
if (timeoutMilliseconds < 0 && timeoutMilliseconds != eShopOnContainers.Windows.Helpers.Timeout.Infinite)
|
||||
throw new ArgumentOutOfRangeException(nameof(timeout));
|
||||
|
||||
if (!cancelToken.HasValue)
|
||||
cancelToken = CancellationToken.None;
|
||||
|
||||
var pos = GetGeolocator().GetGeopositionAsync(TimeSpan.FromTicks(0), TimeSpan.FromDays(365));
|
||||
cancelToken.Value.Register(o => ((IAsyncOperation<Geoposition>)o).Cancel(), pos);
|
||||
var timer = new eShopOnContainers.Windows.Helpers.Timeout(timeoutMilliseconds, pos.Cancel);
|
||||
var tcs = new TaskCompletionSource<Position>();
|
||||
|
||||
pos.Completed = (op, s) =>
|
||||
{
|
||||
timer.Cancel();
|
||||
|
||||
switch (s)
|
||||
{
|
||||
case AsyncStatus.Canceled:
|
||||
tcs.SetCanceled();
|
||||
break;
|
||||
case AsyncStatus.Completed:
|
||||
tcs.SetResult(GetPosition(op.GetResults()));
|
||||
break;
|
||||
case AsyncStatus.Error:
|
||||
var ex = op.ErrorCode;
|
||||
if (ex is UnauthorizedAccessException)
|
||||
ex = new GeolocationException(GeolocationError.Unauthorized, ex);
|
||||
|
||||
tcs.SetException(ex);
|
||||
break;
|
||||
}
|
||||
};
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
@ -115,12 +115,14 @@
|
||||
<Compile Include="Effects\EntryLineColorEffect.cs" />
|
||||
<Compile Include="Extensions\VisualTreeExtensions.cs" />
|
||||
<Compile Include="Helpers\ColorHelper.cs" />
|
||||
<Compile Include="Helpers\Timeout.cs" />
|
||||
<Compile Include="MainPage.xaml.cs">
|
||||
<DependentUpon>MainPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Renderers\CustomTabbedPageRenderer.cs" />
|
||||
<Compile Include="Renderers\SlideDownMenuPageRenderer.cs" />
|
||||
<Compile Include="Services\LocationServiceImplementation.cs" />
|
||||
<Compile Include="Services\SettingsServiceImplementation.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
Loading…
x
Reference in New Issue
Block a user