我如何获得GPS位置更新同步在Android使用Xamarin
本文关键字:Android 使用 Xamarin 同步 更新 何获得 GPS 位置 | 更新日期: 2023-09-27 17:53:28
我正在使用Xamarin进行c#开发。form,但是在原生Android端编写一个GPS包装器类,它将在Xamarin中可用。表单端通过依赖注入。在大多数情况下,c#和Java在Android上的调用应该是相同的。
基本上,我有这个方法在我的Geolocator对象(它在Android端实现了ILocationListener):
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);
}
和
public void OnLocationChanged(Location location) {
gpsData = new GPSData(location.Latitude, location.Longitude);
}
我希望能够调用GetGPSData并让它返回元组,目前关于元组的唯一重要的事情是填充gpsData。我知道找到修复可能需要几秒钟的时间,所以我希望这个方法是异步的,并且在Xamarin中是可等待的。当我真正需要这个值时,在表单端。
我的问题是我想不出一个办法来找经理。RequestSingleUpdate同步工作,或任何工作。你调用那个功能,然后最终OnLocationChanged触发。我试着扔一个恶心的,野蛮的
while (gpsData == null);
调用后强制它不继续,直到OnLocationChanged被触发,然而,当我把那行,OnLocationChanged永远不会被调用。我假设这是因为OnLocationChanged是在同一线程上调用的,而不是后台线程。
是否有任何方法让我采取这种情况,并有GetGPSData不返回,直到OnLocationChanged已经解雇?
感谢编辑:要补充,这个方法将不会被定期调用。这是自发的和罕见的,所以我不想使用RequestLocationUpdates,定期更新,并返回最近的一个,因为这将需要始终有GPS,而会不必要地下雨电池。
您可以用TaskCompletionSource
做您想做的事情。我有同样的问题,这就是我如何解决它:
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;
}
:
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));
}