using Serilog; using System; using System.Threading; using System.Threading.Tasks; using TINK.Model.Device; using Xamarin.Essentials; namespace TINK.Model.Services.Geolocation { public class LastKnownGeolocationService : IGeolocation { private IGeolodationDependent Dependent { get; } public LastKnownGeolocationService(IGeolodationDependent dependent) { Dependent = dependent; } /// Gets the current location. /// Token to cancel request for geolocation. /// Time when geolocation is of interest. Is used to determine whether cached geoloation can be used or not. public async Task GetAsync(CancellationToken? cancelationToken = null, DateTime? timeStamp = null) { Location location; try { location = await Xamarin.Essentials.Geolocation.GetLastKnownLocationAsync(); } catch (FeatureNotSupportedException fnsEx) { // Handle not supported on device exception Log.ForContext().Error("Retrieving Geolocation not supported on device. {Exception}", fnsEx); throw new Exception("Abfrage Standort nicht möglich auf Gerät.", fnsEx); } catch (FeatureNotEnabledException fneEx) { // Handle not enabled on device exception Log.ForContext().Error("Retrieving Geolocation not enabled on device. {Exception}", fneEx); throw new Exception("Abfrage Standort nicht aktiviert auf Gerät.", fneEx); } catch (PermissionException pEx) { // Handle permission exception Log.ForContext().Error("Retrieving Geolocation not permitted on device. {Exception}", pEx); throw new Exception("Berechtiung für Abfrage Standort nicht erteilt für App.", pEx); } catch (Exception ex) { // Unable to get location Log.ForContext().Error("Retrieving Geolocation failed. {Exception}", ex); throw new Exception("Abfrage Standort fehlgeschlagen.", ex); } if (location != null // Cached location is available. && (timeStamp == null || timeStamp.Value.Subtract(location.Timestamp.DateTime) < MaxAge)) { // No time stamp available or location not too old. return location; } return await new GeolocationService(Dependent).GetAsync(cancelationToken, timeStamp); } /// If true location data returned is simulated. public bool IsSimulation { get => false; } /// Maximum age allowed for location info. public TimeSpan MaxAge => new TimeSpan(0, 3 /*minutes*/, 0); public bool IsGeolcationEnabled => Dependent.IsGeolcationEnabled; } }