2017-03-09 68 views
-1

我想收集特定時間段的位置更新,並在最後對位置進行一些操作。我目前記錄方法onLocationChanged的時間。如何收集位置更新以便在onLocationChanged之外進行後續處理

public class LocationProvider implements 
     GoogleApiClient.ConnectionCallbacks, 
     GoogleApiClient.OnConnectionFailedListener, 
     LocationListener { 
    private static final String TAG = LocationProvider.class.getSimpleName(); 

    private Context mContext; 

    private GoogleApiClient mGoogleApiClient; 
    private LocationRequest mLocationRequest; 

    private long mStartTime; 
    private long mDuration; 

    List<Location> locations; 

    public LocationProvider(Context context) { 
     mContext = context; 

     GoogleApiAvailability api = GoogleApiAvailability.getInstance(); 
     if (api.isGooglePlayServicesAvailable(mContext) == ConnectionResult.SUCCESS) { 
      mGoogleApiClient = new GoogleApiClient.Builder(mContext) 
        .addConnectionCallbacks(this) 
        .addOnConnectionFailedListener(this) 
        .addApi(LocationServices.API) 
        .build(); 
     } else { 
      Log.e(TAG, "Could not connect to Google Play services"); 
     } 
    } 

    @Override 
    public void onConnected(Bundle bundle) { 
     LocationServices.FusedLocationApi.requestLocationUpdates(
       mGoogleApiClient, mLocationRequest, this); 
    } 

    @Override 
    public void onConnectionFailed(ConnectionResult connectionResult) { 
     Log.e(TAG, "onConnectionFailed: " + connectionResult.toString()); 
    } 

    @Override 
    public void onConnectionSuspended(int i) { 
     Log.e(TAG, "GoogleApiClient connection has been suspended: " + String.valueOf(i)); 
    } 

    @Override 
    public void onLocationChanged(Location location) { 
     locations.add(location); 

     if (System.currentTimeMillis() - mStartTime > mDuration) { 
      stopTracking(); 
      // do stuff 
     } 
    } 

    public void startTracking(long interval, long fastInterval, long duration) { 
     mDuration = duration; 
     locations = new ArrayList<>(); 

     mLocationRequest = LocationRequest.create() 
       .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY) 
       .setInterval(interval) 
       .setFastestInterval(fastInterval); 

     if (!mGoogleApiClient.isConnected() || !mGoogleApiClient.isConnecting()) { 
      mGoogleApiClient.connect(); 
     } 

     mStartTime = System.currentTimeMillis(); 
    } 

    private void stopTracking() { 
     if (mGoogleApiClient.isConnected()) { 
      LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); 
      mGoogleApiClient.disconnect(); 
     } 
    } 
} 

但是,我想離婚這個邏輯,因爲我想根據我的需要做不同的事情。我推斷,如果我創建了一個用於註冊我的位置偵聽器的新線程,則可以等待主線程,直到完成位置集合以使用locations列表。

public class LocationUpdates { 
    private LocationProvider mLocationProvider; 
    private Looper mLooper; 

    public List<Location> gatherUpdates(final Context context, 
             final long interval, 
             final long fastInterval, 
             final long duration) 
      throws InterruptedException { 

     long startTime = System.currentTimeMillis(); 

     new Thread() { 
      @Override 
      public void run() { 
       Looper.prepare(); 
       mLooper = Looper.myLooper(); 
       mLocationProvider = new LocationProvider(context); 
       mLocationProvider.startTracking(interval, fastInterval, duration); 
       Looper.loop(); 
      } 
     }.start(); 

     while (System.currentTimeMillis() - startTime < duration) { 

     } 

     mLooper.quit(); 
     mLooper.getThread().join(); 

     return mLocationProvider.locations; 
    } 
} 

相反,我觀察到的是(間隔3秒,持續時間10秒):

  • 線達到
  • gatherUpdates返回後然而長
  • onLocationChangedmLocationProvider.startTracking(interval, fastInterval, duration);被稱爲用於第一次只有現在

因此,e雖然位置監聽器已經註冊,但是明顯地阻止它接收更新。我無法弄清楚爲什麼我的邏輯不能達到我期望的目標。

即使沒有線程,是否有方法在收集完成後收集一堆位置更新並在onLocationChanged之外使用它們?

+0

如果downvoter可能好心指出什麼是缺乏在這個問題上,我可能會解決這個問題。這個問題的答案仍然是我感興趣的。 – Reti43

回答

0

您可以使用IntentBroadcastReceiver來構建您的位置更新請求。然後在位置對象的時間超過您的持續時間時刪除更新。

int requestCode = 1; 
Intent intent = new Intent(this, LocationReceiver.class); // Request updates to Receiver 
PendingIntent pendingIntent = PendingIntent.getBroadcast(this, requestCode, intent, PendingIntent.FLAG_CANCEL_CURRENT); 
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, pendingIntent); 

在你的廣播接收器:

@Override 
public void onReceive(Context context, Intent intent) { 

    if(LocationResult.hasResult(intent)){ 
     LocationResult locResult = LocationResult.extractResult(intent); 
     Location location = locResult.getLocations().get(0); 
     // Check the location's time and maybe stop location updates 
    } 
} 
+0

恐怕這似乎沒有幫助我。你所展示的只是如何將位置更新傳遞給BroadcastReceiver,而我已經可以通過LocationListener來完成。我的問題是我有一種方法可以完成任務,然後需要獲取某個特定時間的位置數據,一旦完成,檢索結果並繼續進行業務。問題是如何在不阻止更新的情況下等待該方法。 – Reti43

+0

@ Reti43我建議BroadcastReceiver,因爲他們以及IntentServices可以處理位置Intents,而不需要你的應用程序在前臺。我想說的是,您可以從任何地方請求更新,將位置的值存儲在數據庫中,檢查每次更新的時間以查看它是否符合您的標準,如果沒有,您可以停止存儲數據,如果需要刪除更新,並處理存儲的數據。我不會通過調用wait來接近它。我有一個任務執行預定位處理,另一個任務執行定位後處理。 –