Android FusedLocationApi.getLastLocation同步

时间:2017-06-06 18:48:05

标签: java android google-location-services

我需要将异步FusedLocationApi.getLastLocation调用转换为同步调用。我不是Java的大专家,我不确定我做得对。

我想连接到GoogleApiClient,然后阻止调用线程,直到收到位置信息或错误。应将超时超过10秒的错误视为错误。

它是否会以这种方式工作,或者onConnected也将在主线程上调用,并且此时它将被锁定?

我还注意到lock.wait(TimeUnit.SECONDS.toMillis(10));会在常规运行中立即继续,但在逐步调试中,它会按预期等待10秒。

public class SyncLocationService implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

    public GoogleApiClient mGoogleApiClient;

    public SyncLocationService(Context context) {
        mGoogleApiClient = new GoogleApiClient.Builder(context)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
    }

    private final Object lock = new Object();
    public android.location.Location mLocation;

    @Override
    public android.location.Location lastLocation() {
        mGoogleApiClient.connect();
        synchronized (lock) {
            try {
                lock.wait(TimeUnit.SECONDS.toMillis(10));
            } catch (InterruptedException e) {
                Log.i("NativeLocationService", "InterruptedException");
            }
        }
        return mLocation;
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        try {
            mLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
            mGoogleApiClient.disconnect();
        } catch (SecurityException e) {
            Log.i("NativeLocationService", "SecurityException");
        } finally {
            synchronized (lock) {
                lock.notify();
            }
        }
    }

    @Override
    public void onConnectionSuspended(int i) {

    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        synchronized (lock) {
            lock.notify();
        }
    }
}

基本上我正在尝试重写使用信号量的类似iOS代码。

var semaphore: DispatchSemaphore!
var location: CLLocation!

func lastLocation() -> location? {
    self.semaphore = DispatchSemaphore(value: 0)
    self.locationManager.startUpdatingLocation()
    _ = self.semaphore!.wait(timeout: .now() + 10)  // seconds
    self.semaphore = nil
    return self.location
}

// MARK: - CLLocationManagerDelegate
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
    guard let semaphore = self.semaphore else {
        return
    }
    guard let first = locations.first else {
        return
    }
    self.location = first
    self.locationManager.stopUpdatingLocation()
    semaphore.signal()
}

1 个答案:

答案 0 :(得分:1)

您可以使用GoogleApiClient.blockingConnect()等待连接建立,然后拨打FusedLocationApi.getLastLocation()