package edu.mit.mobile.android.location; /* * Copyright (C) 2011 MIT Mobile Experience Lab * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import android.content.Context; import android.location.Criteria; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.util.Log; import android.widget.Toast; import edu.mit.mobile.android.locast.ver2.R; /** * A wrapper for a LocationManager that incrementally gets location for you, * starting with a coarse locator then moving to a more accurate one. * * @author steve * */ public class IncrementalLocator implements LocationListener { private final static String TAG = IncrementalLocator.class.getSimpleName(); private final LocationManager lm; static final Criteria initialCriteria = new Criteria(); static final Criteria sustainedCriteria = new Criteria(); private boolean gotLocation = false; private String currentProvider; private LocationListener mLocationListener; private final Context mContext; static { initialCriteria.setAccuracy(Criteria.ACCURACY_COARSE); sustainedCriteria.setAccuracy(Criteria.ACCURACY_FINE); } public IncrementalLocator(Context context) { lm = (LocationManager) context .getSystemService(Context.LOCATION_SERVICE); mContext = context; } /** * Registers a locationListener, which will immediately get the last known * location (if there is one). When location updates are no longer needed or * when the activity is paused, please * {@link #removeLocationUpdates(LocationListener)}. * * This can safely be called multiple times for the same listener. * * @param locationListener */ public void requestLocationUpdates(LocationListener locationListener) { // stop any existing location listeners or back out if we're already registered if (mLocationListener != null){ if (mLocationListener != locationListener){ removeLocationUpdates(mLocationListener); }else{ // we're already registered. return; } } mLocationListener = locationListener; final String roughProvider = lm.getBestProvider(initialCriteria, true); if (roughProvider == null) { Toast.makeText(mContext, mContext.getString(R.string.error_no_providers), Toast.LENGTH_LONG).show(); return; } final Location loc = lm.getLastKnownLocation(roughProvider); if (loc != null) { mLocationListener.onLocationChanged(loc); } requestLocationUpdates(roughProvider); if (currentProvider != null) { requestLocationUpdates(currentProvider); } else { Toast.makeText(mContext, R.string.error_no_providers, Toast.LENGTH_LONG).show(); } } private void requestLocationUpdates(String provider) { if (currentProvider != null) { lm.removeUpdates(this); } currentProvider = provider; lm.requestLocationUpdates(provider, 5000, 100, this); lm.requestLocationUpdates(lm.getBestProvider(sustainedCriteria, true), 1000, 100, this); } public boolean isListenerRegistered(LocationListener locListener){ return mLocationListener != null && mLocationListener == locListener; } /** * Unregisters the location listener and stops location updates from coming in. * * @param locListener */ public void removeLocationUpdates(LocationListener locListener) { lm.removeUpdates(this); mLocationListener = null; } public void onLocationChanged(Location location) { if (mLocationListener != null) { if (mLocationListener == this) { Log.e(TAG, "passed IncremetalLocator itself for a location listener"); return; } mLocationListener.onLocationChanged(location); } if (!gotLocation) { final String accurateProvider = lm.getBestProvider( sustainedCriteria, true); requestLocationUpdates(accurateProvider); gotLocation = true; } } public void onProviderDisabled(String provider) { if (mLocationListener != null) { mLocationListener.onProviderDisabled(provider); } } public void onProviderEnabled(String provider) { if (mLocationListener != null) { mLocationListener.onProviderEnabled(provider); } } public Location getLastKnownLocation() { if (currentProvider == null){ return null; } return lm.getLastKnownLocation(currentProvider); } public void onStatusChanged(String provider, int status, Bundle extras) { if (mLocationListener != null) { mLocationListener.onStatusChanged(provider, status, extras); } } }