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