/// <summary> /// Stop listen to location update / gatherer device location. /// </summary> private void StopLocationUpdate(GeolocationStatus status) { if (LocationRetrieveTimer != null) { // Destroy the timer LocationRetrieveTimer.Dispose(); LocationRetrieveTimer = null; } if (FusedLocationClient != null) { // Stop listen to location changes if (FusedLocationCallback != null) { FusedLocationCallback.LocationResult -= FusedLocationCallback_LocationResult; FusedLocationClient.RemoveLocationUpdates(FusedLocationCallback); FusedLocationCallback = null; } FusedLocationClient.Dispose(); FusedLocationClient = null; } if (LocationManager != null) { // Stop listen to location changes LocationManager.RemoveUpdates(this); LocationManager.Dispose(); LocationManager = null; } // Make sure we only update the result if it is not completed yet if (LocationTaskCompletionSource != null && !LocationTaskCompletionSource.Task.IsCompleted) { // Craft the location with all information we have whatever the location is acceptable or not var location = IsLastKnownLocationFresh() ? LastKnownLocation.ToNewGeolocation(status) : new Geolocation(status); // return the location LocationTaskCompletionSource.SetResult(location); } }
/// <summary> /// Start listen to location update / gather device location. /// </summary> private void StartLocationUpdate() { InvokeOnMainThread(async() => { // Don't start another location manager if there is one already running if (FusedLocationClient == null || LocationManager == null) { var isRequestLocationSuccessful = false; var isLastKnownLocationUseable = false; // Check permission if (IsPermissionGrantedImpl()) { // Check if Google Play service is available, if it is available, then we can only use fused location service if (IsGooglePlayLocationAvailableAndEnabled()) { try { FusedLocationClient = LocationServices.GetFusedLocationProviderClient(Application.Context); if (FusedLocationClient != null) { // Try get the last known location or current device location if (!UpdateLocation(await FusedLocationClient.GetLastLocationAsync())) { // Then request the location update var locationRequest = new LocationRequest() .SetPriority(LocationRequest.PriorityHighAccuracy) .SetInterval(5000) // Google document mention 5 seconds .SetFastestInterval(0); FusedLocationCallback = new LocationCallback(); FusedLocationCallback.LocationResult += FusedLocationCallback_LocationResult; await FusedLocationClient.RequestLocationUpdatesAsync(locationRequest, FusedLocationCallback); } else { // No need to get next provider for location since we already have the location isLastKnownLocationUseable = true; } isRequestLocationSuccessful = true; } } catch { // Ignore all error including lack of permission or provider is not enabled } } // In some event that Google Play service is not available or not ready, fall back to Android location instead // Acquire a reference to the system Location Manager if (!isLastKnownLocationUseable) { LocationManager = (LocationManager)Application.Context.GetSystemService(Context.LocationService); if (LocationManager != null && LocationManager.AllProviders != null) { // Get location from all provider to increase the chances of getting a location foreach (var provider in LocationManager.AllProviders) { try { // Try get the last known location or current device location if (!UpdateLocation(LocationManager.GetLastKnownLocation(provider))) { // Then request the location update LocationManager.RequestLocationUpdates(provider, 0, 0f, this); isRequestLocationSuccessful = true; } else { // No need to get next provider for location since we already have the location isRequestLocationSuccessful = true; isLastKnownLocationUseable = true; break; } } catch { // Ignore all error including lack of permission or provider is not enabled } } } } } // Stop location service if initialized failed or we already have the location if (!isRequestLocationSuccessful) { StopLocationUpdate(GeolocationStatus.SetupError); } else if (isLastKnownLocationUseable) { StopLocationUpdate(GeolocationStatus.Successful); } } }); }