c# - current - xamarin ios gps location
¿Cómo obtengo una actualización de ubicación GPS sincrónicamente en Android usando Xamarin? (1)
Específicamente estoy desarrollando C # usando Xamarin.Forms, sin embargo, trabajando en el lado nativo de Android escribiendo una clase de contenedor GPS que se podrá usar en el lado de Xamarin.Forms a través de la inyección de dependencia. Las llamadas deberían ser las mismas entre C # y Java en lo que respecta a Android en su mayor parte.
Esencialmente, tengo este método en mi objeto Geolocator (que implementa ILocationListener) en el lado de Android:
public async Task<Tuple<bool, string, GPSData>> GetGPSData() {
gpsData = null;
var success = false;
var error = string.Empty;
if (!manager.IsProviderEnabled(LocationManager.GpsProvider)) {
//request permission or location services enabling
//set error
} else {
manager.RequestSingleUpdate(LocationManager.GpsProvider, this, null);
success = true;
}
return new Tuple<bool, string, GPSData>(success, error, gpsData);
}
y
public void OnLocationChanged(Location location) {
gpsData = new GPSData(location.Latitude, location.Longitude);
}
Quiero poder llamar a GetGPSData y hacer que devuelva la tupla, que por ahora lo único importante sobre la Tuple es que gpsData está completa. Sé que puede llevar unos segundos encontrar una solución, así que quiero que este método sea asíncrono. y ser a la espera en el lado de Xamarin.Forms una vez que realmente necesito el valor.
Mi problema es que no puedo encontrar la manera de tener manager.RequestSingleUpdate funciona de forma síncrona, o cualquier solución alternativa. Llamas a ese método y luego, con el tiempo, OnLocationChanged se desactiva. Intenté arrojar algo repugnante y bárbaro
while (gpsData == null);
después de la llamada para forzarlo a no continuar hasta que se activó OnLocationChanged, sin embargo, cuando introduzco esa línea, nunca se llama a OnLocationChanged. Supongo que es porque OnLocationChanged se invoca en el mismo hilo en lugar de ser un hilo de fondo.
¿Hay alguna forma de que tome este escenario y que GetGPSData no regrese hasta que OnLocationChanged se haya apagado?
Gracias
EDITAR: para agregar, este método no se llamará regularmente. Es espontáneo y raro, así que no quiero utilizar RequestLocationUpdates, obtener actualizaciones periódicas y devolver la más reciente porque eso requeriría tener siempre el GPS encendido, mientras que llovería las baterías innecesariamente.
Puede hacer lo que quiera con TaskCompletionSource
. Tuve el mismo problema y así es como lo resolví:
TaskCompletionSource<Tuple<bool, string, GPSData> tcs;
// No need for the method to be async, as nothing is await-ed inside it.
public Task<Tuple<bool, string, GPSData>> GetGPSData() {
tcs = new TaskCompletionSource<Tuple<bool, string, GPSData>>();
gpsData = null;
var success = false;
var error = string.Empty;
if (!manager.IsProviderEnabled(LocationManager.GpsProvider)) {
//request permission or location services enabling
//set error
tcs.TrySetException(new Exception("some error")); // This will throw on the await-ing caller of this method.
} else {
manager.RequestSingleUpdate(LocationManager.GpsProvider, this, null);
success = true;
}
//return new Tuple<bool, string, GPSData>(success, error, gpsData); <-- change this to:
return this.tcs.Task;
}
Y:
public void OnLocationChanged(Location location) {
gpsData = new GPSData(location.Latitude, location.Longitude);
// Here you set the result of TaskCompletionSource. Your other method completes the task and returns the result to its caller.
tcs.TrySetResult(new Tuple<bool, string, GPSData>(false, "someString", gpsData));
}