using gehGassi.Dto.Common; using gehGassiApp.Core.Common; using gehGassiApp.Core.Interfaces; using gehGassiApp.Domain.Common; namespace gehGassiApp.Core.Services { /// /// Hilfs-Service bei der Lokalisierung eines Benutzers /// public class LocationService : ILocationService { private readonly ICountryService _countryService; private readonly ISettingsService _settingsService; private readonly IAppReportingService _appReportingService; private LocationDto _cachedLocation; private DateTimeOffset? _lastUpdate; private DateTimeOffset? _lastReceivedNull; /// /// Erstellt eine Instanz /// /// Instanz eines ICountryService /// Instanz eines ISettingsService /// Instanz eines IAppReportingService public LocationService(ICountryService countryService, ISettingsService settingsService, IAppReportingService appReportingService) { _countryService = countryService; _settingsService = settingsService; _appReportingService = appReportingService; _lastUpdate = null; _lastReceivedNull = null; _cachedLocation = null; } /// /// Holen der Lat und Lng sowie, wenn möglich Land und Bundesland /// /// Aktuelle Position des Benutzers, oder null wenn nicht möglich public async Task GetLocationAsync() { if (_cachedLocation != null && _lastUpdate != null && _lastUpdate > DateTimeOffset.UtcNow) { return _cachedLocation; } var location = new LocationDto(); try { var appSettings = _settingsService.GetAppSettings(); if (appSettings.FakeGps) { var locationDto = new LocationDto { Lat = appSettings.Latitude, Lng = appSettings.Longitude }; var placemarks = await Geocoding.Default.GetPlacemarksAsync(locationDto.Lat.Value, locationDto.Lng.Value); if (placemarks != null && placemarks.Any()) { var placemark = placemarks.FirstOrDefault(); locationDto.CountryCode = placemark.CountryCode.ToUpper(); var state = await _countryService.GetStateByNameAsync(location.CountryCode, placemark.AdminArea); if (state != null) locationDto.StateCode = state.Code; } return locationDto; } var status = await Permissions.CheckStatusAsync(); if (status == PermissionStatus.Granted) { var foundLocation = await Geolocation.Default.GetLastKnownLocationAsync(); if (foundLocation == null && (_lastReceivedNull == null || _lastReceivedNull > DateTimeOffset.UtcNow)) { //Wenn nichts im Cache, direkt holen. Kann länger dauern using var cts = new CancellationTokenSource(Constants.GpsRealtimeTimout); foundLocation = await Geolocation.Default.GetLocationAsync(new GeolocationRequest(GeolocationAccuracy.Medium, Constants.GpsRealtimeTimout), cts.Token); if (foundLocation == null) { _lastReceivedNull = DateTimeOffset.UtcNow.Add(Constants.LocationCacheTimeout); } } if (foundLocation != null) { _lastReceivedNull = null; location.Lat = foundLocation.Latitude; location.Lng = foundLocation.Longitude; var placemarks = await Geocoding.Default.GetPlacemarksAsync(foundLocation); if (placemarks != null && placemarks.Any()) { var placemark = placemarks.FirstOrDefault(); location.CountryCode = placemark.CountryCode.ToUpper(); var state = await _countryService.GetStateByNameAsync(location.CountryCode, placemark.AdminArea); if (state != null) location.StateCode = state.Code; } } } } catch { location = new LocationDto(); } _cachedLocation = location; if (_cachedLocation.Lat == null && _cachedLocation.Lng == null) _cachedLocation = null; if (_cachedLocation != null) _lastUpdate = DateTimeOffset.UtcNow.Add(Constants.LocationCacheTimeout); else _lastUpdate = null; return location; } /// /// Gibt Lat und Long anhand einer Adresse zurück, wenn möglich /// /// Adresse /// Location mit Lat und Lng oder null wenn nicht möglich public async Task GetLocationByAddressAsync(Address address) { if (address != null) { var status = await Permissions.CheckStatusAsync(); if (status == PermissionStatus.Granted) { try { var locations = await Geocoding.Default.GetLocationsAsync($"{address.AddressLine1} {address.Zip} {address.City} {address.CountryCode}"); var location = locations?.FirstOrDefault(); return location; } catch(Exception ex) { await _appReportingService.TrackErrorAsync(ex); } } } return null; } /// /// Gibt, wenn möglich, die aktuelle Adresse zu einer Position zurück /// /// Adresse oder null, wenn keine gefunden public async Task
GetAddressByCurrentLocationAsync() { var location = new LocationDto(); try { var appSettings = _settingsService.GetAppSettings(); if (appSettings.FakeGps) { var locationDto = new LocationDto { Lat = appSettings.Latitude, Lng = appSettings.Longitude }; var placemarks = await Geocoding.Default.GetPlacemarksAsync(locationDto.Lat.Value, locationDto.Lng.Value); if (placemarks != null && placemarks.Any()) { var placemark = placemarks.FirstOrDefault(); var countryCode = placemark.CountryCode.ToUpper(); var stateCode = string.Empty; var state = await _countryService.GetStateByNameAsync(location.CountryCode, placemark.AdminArea); if (state != null) stateCode = state.Code; var address = new Address { AddressLine1 = placemark.Thoroughfare, AddressLine2 = string.Empty, Zip = placemark.PostalCode, City = placemark.Locality, State = stateCode, CountryCode = countryCode }; if (!string.IsNullOrWhiteSpace(placemark.SubThoroughfare)) address.AddressLine1 += $" {placemark.SubThoroughfare}"; if (!string.IsNullOrWhiteSpace(address.AddressLine1) && !string.IsNullOrWhiteSpace(address.Zip) && !string.IsNullOrWhiteSpace(address.City) && !string.IsNullOrWhiteSpace(address.State) && !string.IsNullOrWhiteSpace(address.CountryCode)) return address; else return null; } return null; } var status = await Permissions.CheckStatusAsync(); if (status == PermissionStatus.Granted) { var foundLocation = await Geolocation.Default.GetLastKnownLocationAsync(); if (foundLocation == null) { //Wenn nichts im Cache, direkt holen. Kann länger dauern using var cts = new CancellationTokenSource(Constants.GpsRealtimeTimout); foundLocation = await Geolocation.Default.GetLocationAsync(new GeolocationRequest(GeolocationAccuracy.Medium, Constants.GpsRealtimeTimout), cts.Token); } if (foundLocation != null) { location.Lat = foundLocation.Latitude; location.Lng = foundLocation.Longitude; var placemarks = await Geocoding.Default.GetPlacemarksAsync(foundLocation); if (placemarks != null && placemarks.Any()) { var placemark = placemarks.FirstOrDefault(); var countryCode = placemark.CountryCode.ToUpper(); var stateCode = string.Empty; var state = await _countryService.GetStateByNameAsync(countryCode, placemark.AdminArea); if (state != null) stateCode = state.Code; var address = new Address { AddressLine1 = placemark.Thoroughfare, AddressLine2 = string.Empty, Zip = placemark.PostalCode, City = placemark.Locality, State = stateCode, CountryCode = countryCode }; if (!string.IsNullOrWhiteSpace(placemark.SubThoroughfare)) address.AddressLine1 += $" {placemark.SubThoroughfare}"; //return address; if (!string.IsNullOrWhiteSpace(address.AddressLine1) && !string.IsNullOrWhiteSpace(address.Zip) && !string.IsNullOrWhiteSpace(address.City) && !string.IsNullOrWhiteSpace(address.State) && !string.IsNullOrWhiteSpace(address.CountryCode)) return address; else return null; } } } } catch(Exception ex) { await _appReportingService.TrackErrorAsync(ex); } return null; } } }