Android FusedLocationApi.getLastLocation 同步
Android FusedLocationApi.getLastLocation Synchronously
我需要将异步 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()
}
您可以使用GoogleApiClient.blockingConnect()
等待连接建立,然后调用FusedLocationApi.getLastLocation()
。
我需要将异步 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()
}
您可以使用GoogleApiClient.blockingConnect()
等待连接建立,然后调用FusedLocationApi.getLastLocation()
。