2017-06-06 76 views
0

我需要將異步FusedLocationApi.getLastLocation調用轉換爲同步。我不是Java的大專家,我不確定我是否做對了。Android FusedLocationApi.getLastLocation同步

我想連接到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() 
} 
+0

看看這個答案:https://stackoverflow.com/questions/36740758/how-to-return-value-on-googleapiclient-onconnected – Entreco

回答

1

您可以使用GoogleApiClient.blockingConnect()等到建立連接,然後調用FusedLocationApi.getLastLocation()