Browse Source

UWP location service added.

pull/521/head
David Britch 7 years ago
parent
commit
d2bd5a55ec
3 changed files with 201 additions and 0 deletions
  1. +33
    -0
      src/Mobile/eShopOnContainers/eShopOnContainers.Windows/Helpers/Timeout.cs
  2. +166
    -0
      src/Mobile/eShopOnContainers/eShopOnContainers.Windows/Services/LocationServiceImplementation.cs
  3. +2
    -0
      src/Mobile/eShopOnContainers/eShopOnContainers.Windows/eShopOnContainers.Windows.csproj

+ 33
- 0
src/Mobile/eShopOnContainers/eShopOnContainers.Windows/Helpers/Timeout.cs View File

@ -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();
}
}
}

+ 166
- 0
src/Mobile/eShopOnContainers/eShopOnContainers.Windows/Services/LocationServiceImplementation.cs View File

@ -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
}
}

+ 2
- 0
src/Mobile/eShopOnContainers/eShopOnContainers.Windows/eShopOnContainers.Windows.csproj View File

@ -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…
Cancel
Save