255 lines
11 KiB
C#
255 lines
11 KiB
C#
using gehGassi.Dto.Common;
|
|
using gehGassiApp.Core.Common;
|
|
using gehGassiApp.Core.Interfaces;
|
|
using gehGassiApp.Domain.Common;
|
|
|
|
namespace gehGassiApp.Core.Services
|
|
{
|
|
/// <summary>
|
|
/// Hilfs-Service bei der Lokalisierung eines Benutzers
|
|
/// </summary>
|
|
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;
|
|
|
|
/// <summary>
|
|
/// Erstellt eine Instanz
|
|
/// </summary>
|
|
/// <param name="countryService">Instanz eines ICountryService</param>
|
|
/// <param name="settingsService">Instanz eines ISettingsService</param>
|
|
/// <param name="appReportingService">Instanz eines IAppReportingService</param>
|
|
public LocationService(ICountryService countryService, ISettingsService settingsService, IAppReportingService appReportingService)
|
|
{
|
|
_countryService = countryService;
|
|
_settingsService = settingsService;
|
|
_appReportingService = appReportingService;
|
|
_lastUpdate = null;
|
|
_lastReceivedNull = null;
|
|
_cachedLocation = null;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Holen der Lat und Lng sowie, wenn möglich Land und Bundesland
|
|
/// </summary>
|
|
/// <returns>Aktuelle Position des Benutzers, oder null wenn nicht möglich</returns>
|
|
public async Task<LocationDto> 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<Permissions.LocationWhenInUse>();
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt Lat und Long anhand einer Adresse zurück, wenn möglich
|
|
/// </summary>
|
|
/// <param name="address">Adresse</param>
|
|
/// <returns>Location mit Lat und Lng oder null wenn nicht möglich</returns>
|
|
public async Task<Location> GetLocationByAddressAsync(Address address)
|
|
{
|
|
if (address != null)
|
|
{
|
|
var status = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>();
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gibt, wenn möglich, die aktuelle Adresse zu einer Position zurück
|
|
/// </summary>
|
|
/// <returns>Adresse oder null, wenn keine gefunden</returns>
|
|
public async Task<Address> 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<Permissions.LocationWhenInUse>();
|
|
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;
|
|
}
|
|
}
|
|
}
|