123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- using System;
- using System.Threading.Tasks;
- using System.Linq;
- using Xamarin.Forms;
- using Xamarin.Essentials;
- namespace InABox.Mobile
- {
- public class LocationServices
- {
- public delegate void LocationEvent(LocationServices sender);
- public event LocationEvent OnLocationFound;
- public delegate void LocationError(LocationServices sender, Exception error);
- public event LocationError OnLocationError;
- public TimeSpan ScanDelay { get; set; }
- public double Latitude { get; private set; }
- public double Longitude { get; private set; }
- public String Address { get; private set; }
- private bool bLocating = false;
- public DateTime TimeStamp { get; private set; }
- public LocationServices() : base()
- {
- TimeStamp = DateTime.MinValue;
- ScanDelay = new TimeSpan(0, 0, 0);
- Address = "Searching for GPS";
- }
- public bool RecentlyLocated
- {
- get
- {
- return (DateTime.Now.Subtract(TimeStamp).Ticks < ScanDelay.Ticks);
- }
- }
- private double DistanceBetween(double sLatitude, double sLongitude, double eLatitude,
- double eLongitude)
- {
- var radiansOverDegrees = (Math.PI / 180.0);
- var sLatitudeRadians = sLatitude * radiansOverDegrees;
- var sLongitudeRadians = sLongitude * radiansOverDegrees;
- var eLatitudeRadians = eLatitude * radiansOverDegrees;
- var eLongitudeRadians = eLongitude * radiansOverDegrees;
- var dLongitude = eLongitudeRadians - sLongitudeRadians;
- var dLatitude = eLatitudeRadians - sLatitudeRadians;
- var result1 = Math.Pow(Math.Sin(dLatitude / 2.0), 2.0) +
- Math.Cos(sLatitudeRadians) * Math.Cos(eLatitudeRadians) *
- Math.Pow(Math.Sin(dLongitude / 2.0), 2.0);
- // Using 3956 as the number of miles around the earth
- var result2 = 3956.0 * 2.0 *
- Math.Atan2(Math.Sqrt(result1), Math.Sqrt(1.0 - result1));
- return result2;
- }
- public void GetLocation(bool skiprecentlylocated = false)
- {
- if (bLocating || RecentlyLocated)
- {
- if (!skiprecentlylocated)
- return;
- }
- bLocating = true;
- // Don't reset this on every refresh, otherwise the final UI will randomly get "Searching for GPS" as the address
- //Address = "Searching for GPS";
- bool bOK = MobileUtils.IsPermitted<Permissions.LocationWhenInUse>().Result;
-
- Task.Run(async () =>
- {
- try
- {
-
- if (!bOK)
- {
- Latitude = 0.0F;
- Longitude = 0.0F;
- TimeStamp = DateTime.MinValue;
- Address = "GPS Services Disabled";
- Device.BeginInvokeOnMainThread(() =>
- {
- OnLocationError?.Invoke(this, new Exception("Please enable GPS Services to continue"));
- });
- bOK = false;
- bLocating = false;
- }
- else
- {
- try
- {
- var request = new GeolocationRequest(GeolocationAccuracy.Best, new TimeSpan(0, 0, 20));
- var location = await Geolocation.GetLocationAsync(request);
- if (location != null)
- {
- //if (location.IsFromMockProvider)
- //{
- // Device.BeginInvokeOnMainThread(() =>
- // {
- // OnLocationError?.Invoke(this, new Exception("Mock GPS Location Detected!\nPlease correct and restart TimeBench."));
- // });
- //}
- //else
- {
- Latitude = location.Latitude;
- Longitude = location.Longitude;
- TimeStamp = DateTime.Now;
- String sErr = "";
- Placemark address = null;
- try
- {
- var addresses = await Geocoding.GetPlacemarksAsync(Latitude, Longitude);
- double maxdist = double.MaxValue;
- foreach (var cur in addresses.Where(x => !String.IsNullOrEmpty(x.Thoroughfare)))
- {
- var delta = Location.CalculateDistance(location, cur.Location, DistanceUnits.Kilometers);
- if (delta < maxdist)
- {
- address = cur;
- maxdist = delta;
- }
- }
- }
-
- catch (Exception ee2)
- {
- sErr = ee2.Message;
- //address = null;
- }
- if (address != null)
- Address = String.Format("{0} {1} {2}", address.SubThoroughfare, address.Thoroughfare, address.Locality);
- else
- Address = String.Format("Lat: {0}, Lng: {1}", Latitude, Longitude);
- if (location.IsFromMockProvider)
- Address = "** " + Address;
- if (!String.IsNullOrEmpty(sErr))
- Address = String.Format("{0} (ERROR: {1})", Address, sErr);
- Device.BeginInvokeOnMainThread(() =>
- {
- OnLocationFound?.Invoke(this);
- });
- bLocating = false;
- }
- }
- else
- {
- Latitude = 0.00;
- Longitude = 0.00;
- TimeStamp = DateTime.MinValue;
- bLocating = false;
- Device.BeginInvokeOnMainThread(() =>
- {
- OnLocationError?.Invoke(this, new Exception("Unable to get GPS Location"));
- });
- }
- }
- catch (Exception e)
- {
- bLocating = false;
- Device.BeginInvokeOnMainThread(() =>
- {
- OnLocationError?.Invoke(this, e);
- });
- }
- }
- }
- catch (Exception e)
- {
-
- }
- bLocating = false;
- });
- }
- }
- }
|