如何使用Xamarin在Android中同步获取GPS位置更新?

具体来说,我正在使用Xamarin.Forms进行C#开发,但是在本机Android方面工作,编写了GPS包装类,该类可以通过依赖注入在Xamarin.Forms方面使用.在大多数情况下,关于Android,C#和Java之间的调用应该相同.

本质上,我在Android端的Geolocator对象(实现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.Forms端等待.

我的问题是我想不出一种方法来让manager.RequestSingleUpdate同步工作或进行其他工作.您调用方法,然后最终触发OnLocationChanged.我试图投掷令人作呕的野蛮人

 while (gpsData == null);

在强制它在OnLocationChanged被触发之前不要继续进行的调用之后,但是当我将该行放入时,永远不会调用OnLocationChanged.我假设这是因为OnLocationChanged是在同一线程而不是后台线程上调用的.

我有什么办法可以采取这种情况,并在OnLocationChanged触发之前不返回GetGPSData?

谢谢

编辑:要添加,此方法将不会定期调用.它是自发的,很少见,所以我不想使用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));
    }

相关文章

Android性能优化——之控件的优化 前面讲了图像的优化,接下...
前言 上一篇已经讲了如何实现textView中粗字体效果,里面主要...
最近项目重构,涉及到了数据库和文件下载,发现GreenDao这个...
WebView加载页面的两种方式 一、加载网络页面 加载网络页面,...
给APP全局设置字体主要分为两个方面来介绍 一、给原生界面设...
前言 最近UI大牛出了一版新的效果图,按照IOS的效果做的,页...