我如何获得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,而会不必要地下雨电池。

我如何获得GPS位置更新同步在Android使用Xamarin

您可以用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));
    }