package edu.mit.mitmobile2.facilities; import java.util.List; import android.content.Context; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.ListView; import android.widget.Toast; import edu.mit.mitmobile2.FullScreenLoader; import edu.mit.mitmobile2.NewModule; import edu.mit.mitmobile2.NewModuleActivity; import edu.mit.mitmobile2.R; import edu.mit.mitmobile2.TitleBar; import edu.mit.mitmobile2.TwoLineActionRow; import edu.mit.mitmobile2.objs.FacilitiesItem.LocationRecord; public class FacilitiesUseMyLocationActivity extends NewModuleActivity { public static final String TAG = "FacilitiesLocationsNearByActivity"; private static final int REASONABLE_LOCATION_AGE = 90 * 1000; // 90 seconds private static final int SUFFICIENT_ACCURACY = 100; // 100 meters; private static final int MAX_WAIT_TIME = 6000; // do not wait more than 5000 miliseconds private Location mLocation; private LocationListener mLocationListener; boolean mLocationSet = false; boolean mLocationErrorShown = false; Context mContext; ListView mListView; final FacilitiesDB db = FacilitiesDB.getInstance(this); FullScreenLoader mLoader; private Handler uiHandler; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Log.d(TAG,"onCreate()"); mContext = this; uiHandler = new Handler(); uiHandler.postDelayed( new Runnable() { @Override public void run() { loadLocations(); } }, MAX_WAIT_TIME); createViews(); LocationManager locManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE); mLocationListener = new MyLocationListener(); Location lastKnownLocation = lastKnownLocation(); if(isReasonableLocation(lastKnownLocation)) { mLocation = lastKnownLocation; loadLocations(); } else { locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mLocationListener); locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, mLocationListener); } } @Override public void onPause() { super.onPause(); LocationManager locManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE); locManager.removeUpdates(mLocationListener); } private boolean isRecentLocation(Location location) { if(location != null) { return System.currentTimeMillis() - location.getTime() < REASONABLE_LOCATION_AGE; } return false; } private boolean isReasonableLocation(Location location) { if(location != null) { if(isRecentLocation(location)) { return location.getAccuracy() < SUFFICIENT_ACCURACY; } } return false; } private Location lastKnownLocation() { LocationManager locManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE); Location lastGPS = locManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); Location lastNetwork = locManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); if(isRecentLocation(lastGPS)) { return lastGPS; } if(isRecentLocation(lastNetwork)) { return lastNetwork; } // for simplicity fallback to the lastGPS return lastGPS; } public void loadLocations() { if(!mLocationSet) { mLocationSet = true; LocationManager locManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE); locManager.removeUpdates(mLocationListener); // if no location found attempt to fall back // to last known location if(mLocation == null) { mLocation = lastKnownLocation(); } if(mLocation == null) { FacilitiesUseMyLocationActivity.this.locationNotFound(); return; // early exit } new Thread() { @Override public void run() { FacilitiesDB db = FacilitiesDB.getInstance(mContext); List<LocationRecord> allLocations = db.getLocationsNearLocation(mLocation); final List<LocationRecord> closestLocations = allLocations.subList(0, 10); uiHandler.post(new Runnable() { @Override public void run() { mListView.setAdapter(new LocationArrayAdapter(mContext, 0, closestLocations)); mListView.setVisibility(View.VISIBLE); mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { LocationRecord location = closestLocations.get(position); FacilitiesActivity.launchActivityForLocation(mContext, location); } }); mLoader.setVisibility(View.GONE); } }); } }.start(); } } public void createViews() { setContentView(R.layout.boring_list_layout); TitleBar titleBar = (TitleBar) findViewById(R.id.boringListTitleBar); titleBar.setVisibility(View.GONE); addSecondaryTitle("Nearby Locations"); mLoader = (FullScreenLoader) findViewById(R.id.boringListLoader); mLoader.showLoading(); mListView = (ListView) findViewById(R.id.boringListLV); } private void locationNotFound() { if(!mLocationErrorShown) { Toast.makeText(this, "No location found please check your settings", Toast.LENGTH_LONG).show(); finish(); mLocationErrorShown = true; } } /* Class My Location Listener */ public class MyLocationListener implements LocationListener { @Override public void onLocationChanged(Location loc){ loc.getLatitude(); loc.getLongitude(); if (mLocation == null) { mLocation = loc; } else if (loc.getAccuracy() < mLocation.getAccuracy()) { mLocation = loc; } if (mLocation.getAccuracy() < SUFFICIENT_ACCURACY) { loadLocations(); } } @Override public void onProviderDisabled(String arg0) { FacilitiesUseMyLocationActivity.this.locationNotFound(); } @Override public void onProviderEnabled(String provider) { // TODO Auto-generated method stub } @Override public void onStatusChanged(String provider, int status, Bundle extras) { // TODO Auto-generated method stub } } @Override public boolean isModuleHomeActivity() { // TODO Auto-generated method stub return false; } private static class LocationArrayAdapter extends ArrayAdapter<LocationRecord> { private Context mContext; public LocationArrayAdapter(Context context, int textViewResourceId, List<LocationRecord> objects) { super(context, textViewResourceId, objects); mContext = context; } @Override public View getView(int position, View convertView, ViewGroup parent) { if(convertView == null) { convertView = new TwoLineActionRow(mContext); } LocationRecord item = getItem(position); LocationAdapter.populateView(item, convertView); return convertView; } } @Override protected NewModule getNewModule() { // TODO Auto-generated method stub return new FacilitiesModule(); } @Override protected boolean isScrollable() { // TODO Auto-generated method stub return false; } @Override protected void onOptionSelected(String optionId) { // TODO Auto-generated method stub } }