2017-03-09 36 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来接近它。我有一个任务执行预定位处理,另一个任务执行定位后处理。 –

相关问题