using System; using System.Threading; using System.Threading.Tasks; using Billing.Models; using Billing.UI; using Xamarin.Essentials; using Xamarin.Forms; using Xamarin.Forms.Maps; using Xamarin.Forms.PlatformConfiguration.iOSSpecific; using Map = Xamarin.Forms.Maps.Map; namespace Billing.Views { public class ViewLocationPage : BillingPage { public event EventHandler<Location> Synced; private readonly Bill bill; private CancellationTokenSource tokenSource; public ViewLocationPage(Bill bill) { On<Xamarin.Forms.PlatformConfiguration.iOS>().SetUseSafeArea(false); this.bill = bill; Title = bill.Name; ToolbarItems.Add(new ToolbarItem { IconImageSource = "location.png", Order = ToolbarItemOrder.Primary, Command = new Command(OnSynced) }); if (bill.Latitude != null && bill.Longitude != null) { var (longitude, latitude) = (bill.Longitude.Value, bill.Latitude.Value).Wgs84ToGcj02(); var position = new Position(latitude, longitude); var mapSpan = new MapSpan(position, 0.01, 0.01); Content = new Map(mapSpan) { Pins = { new Pin { Label = bill.Name, Type = PinType.Generic, Position = position, Address = bill.Store } } }; } } protected override void OnDisappearing() { if (tokenSource != null && !tokenSource.IsCancellationRequested) { tokenSource.Cancel(); } base.OnDisappearing(); } private async void OnSynced() { if (Tap.IsBusy) { return; } using (Tap.Start()) { if (tokenSource != null) { return; } var location = await GetCurrentLocation(); if (location != null) { Synced?.Invoke(this, location); MainThread.BeginInvokeOnMainThread(() => { var (longitude, latitude) = (location.Longitude, location.Latitude).Wgs84ToGcj02(); var position = new Position(latitude, longitude); var mapSpan = new MapSpan(position, 0.01, 0.01); Content = new Map(mapSpan) { Pins = { new Pin { Label = bill.Name, Type = PinType.Generic, Position = position, Address = bill.Store } } }; }); } } } private async Task<Location> GetCurrentLocation() { try { var request = new GeolocationRequest(GeolocationAccuracy.Best, TimeSpan.FromSeconds(10)); tokenSource = new CancellationTokenSource(); var status = await Helper.CheckAndRequestPermissionAsync<Permissions.LocationWhenInUse>(); if (status != PermissionStatus.Granted) { return null; } return await Geolocation.GetLocationAsync(request, tokenSource.Token); } catch (FeatureNotSupportedException) { } catch (FeatureNotEnabledException) { } catch (PermissionException) { } catch (Exception ex) { Helper.Error("location.get", ex); } tokenSource = null; return null; } } }