/* * Southampton University Map App * Copyright (C) 2011 Christopher Baines * * 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. */ package net.cbaines.suma; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.osmdroid.util.GeoPoint; import android.content.Context; import android.content.Intent; import android.location.Location; import android.location.LocationListener; import android.location.LocationManager; import android.net.Uri; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; import android.util.Log; import android.view.Gravity; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemLongClickListener; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ProgressBar; import com.j256.ormlite.android.apptools.OrmLiteBaseActivity; import com.j256.ormlite.dao.Dao; import com.j256.ormlite.stmt.PreparedQuery; import com.j256.ormlite.stmt.QueryBuilder; public class FindActivity extends OrmLiteBaseActivity implements Runnable, TextWatcher, OnItemClickListener, LocationListener, OnItemLongClickListener { final static String TAG = "FindActivity"; private EditText searchBar; private ListView listItems; private ProgressBar progBar; private LinearLayout findContentLayout; private String searchTerm = ""; private Dao buildingDao; private Dao busStopDao; private Dao siteDao; private POIArrayAdapter adapter; private GeoPoint userLocation; private Thread searchThread; ArrayList getNearestPOIs(int distance) { Log.i(TAG, "Getting nearest POI's"); ArrayList nearestPOIs = new ArrayList(); for (Iterator buildingDaoIter = buildingDao.iterator(); buildingDaoIter.hasNext();) { POI poi = buildingDaoIter.next(); int dist = poi.point.distanceTo(userLocation); if (dist < distance) { poi.distTo = dist; nearestPOIs.add(poi); } } for (Iterator busStopDaoIter = busStopDao.iterator(); busStopDaoIter.hasNext();) { POI poi = busStopDaoIter.next(); int dist = poi.point.distanceTo(userLocation); if (dist < distance) { poi.distTo = dist; nearestPOIs.add(poi); } } Collections.sort(nearestPOIs, new POIDistanceComparator(userLocation, true)); Log.i(TAG, "Got " + nearestPOIs.size() + " nearest POI's"); return nearestPOIs; } // Search thread public void run() { POIArrayAdapter tempAdaptor; GeoPoint thisUserLocation = userLocation; Log.i(TAG, "Search thread started"); String thisSearchTerm = searchTerm; ArrayList foundPOIsArray = null; Log.i(TAG, "Search term length " + thisSearchTerm.length() + " userLocation == null " + (thisUserLocation == null)); if (thisSearchTerm.length() == 0 && thisUserLocation != null) { foundPOIsArray = getNearestPOIs(200); } if (foundPOIsArray != null && foundPOIsArray.size() != 0) { tempAdaptor = new POIArrayAdapter(this, foundPOIsArray); } else { try { foundPOIsArray = new ArrayList(); if (thisSearchTerm.length() == 0) { for (Building building : buildingDao) { foundPOIsArray.add(building); } if (!thisSearchTerm.equals(searchTerm)) return; for (BusStop busStop : busStopDao) { foundPOIsArray.add(busStop); } if (!thisSearchTerm.equals(searchTerm)) return; for (Site site : siteDao) { foundPOIsArray.add(site); } } else { QueryBuilder buildingQueryBuilder = buildingDao.queryBuilder(); buildingQueryBuilder.where().like(Building.ID_FIELD_NAME, "%" + thisSearchTerm + "%").or() .like(Building.NAME_FIELD_NAME, "%" + thisSearchTerm + "%"); PreparedQuery buildingPreparedQuery = buildingQueryBuilder.prepare(); List buildings = buildingDao.query(buildingPreparedQuery); for (Building building : buildings) { foundPOIsArray.add(building); } buildings = null; if (!thisSearchTerm.equals(searchTerm)) return; if (thisSearchTerm.contains("site")) { for (Site site : siteDao) { foundPOIsArray.add(site); } } else { QueryBuilder siteQueryBuilder = siteDao.queryBuilder(); siteQueryBuilder.where().like(Site.ID_FIELD_NAME, "%" + thisSearchTerm + "%").or() .like(Site.NAME_FIELD_NAME, "%" + thisSearchTerm + "%"); PreparedQuery sitePreparedQuery = siteQueryBuilder.prepare(); List sites = siteDao.query(sitePreparedQuery); for (Site site : sites) { foundPOIsArray.add(site); } sites = null; } if (!thisSearchTerm.equals(searchTerm)) return; // if (thisSearchTerm.contains("bus")) { // for (BusStop busStop : busStopDao) { // foundPOIsArray.add(busStop); // } // } else { QueryBuilder busStopQueryBuilder = busStopDao.queryBuilder(); busStopQueryBuilder.where().like(BusStop.ID_FIELD_NAME, "%" + thisSearchTerm + "%").or() .like(BusStop.DESCRIPTION_FIELD_NAME, "%" + thisSearchTerm + "%"); PreparedQuery busStopPreparedQuery = busStopQueryBuilder.prepare(); List busStops = busStopDao.query(busStopPreparedQuery); for (BusStop busStop : busStops) { foundPOIsArray.add(busStop); } busStops = null; // } if (!thisSearchTerm.equals(searchTerm)) return; Log.i(TAG, "Found " + foundPOIsArray.size() + " pois"); if (thisUserLocation != null) { Collections.sort(foundPOIsArray, new POIDistanceComparator(userLocation)); } else { Collections.sort(foundPOIsArray, new StringDistanceComparator(thisSearchTerm)); } } if (!thisSearchTerm.equals(searchTerm)) return; tempAdaptor = new POIArrayAdapter(this, foundPOIsArray); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); return; } } if (thisSearchTerm.equals(searchTerm)) { Log.i(TAG, "Search terms still equal, starting post"); adapter = tempAdaptor; listItems.post(new Runnable() { public void run() { listItems.setAdapter(adapter); if (progBar.getVisibility() != View.GONE) { progBar.setVisibility(View.GONE); findContentLayout.setGravity(Gravity.TOP); } } }); } else { Log.i(TAG, "Search terms no longer equal, exiting"); } } /** Called when the activity is first created. */ public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.find_activity); searchBar = (EditText) findViewById(R.id.searchBar); searchBar.addTextChangedListener(this); listItems = (ListView) findViewById(R.id.findListItems); listItems.setOnItemClickListener(this); listItems.setOnItemLongClickListener(this); progBar = (ProgressBar) findViewById(R.id.findLoadBar); findContentLayout = (LinearLayout) findViewById(R.id.findContentLayout); try { buildingDao = getHelper().getBuildingDao(); busStopDao = getHelper().getBusStopDao(); siteDao = getHelper().getSiteDao(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } // Acquire a reference to the system Location Manager LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); Location lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER); if (lastKnownLocation != null) { userLocation = Util.locationToGeoPoint(lastKnownLocation); } else { lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); if (lastKnownLocation != null) { userLocation = Util.locationToGeoPoint(lastKnownLocation); } } // Register the listener with the Location Manager to receive location // updates locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 10000, 10, this); try { locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 10000, 10, this); } catch (Exception e) { // Ignore anything that goes wrong here... } searchThread = new Thread(this); searchThread.start(); } public void afterTextChanged(Editable s) { searchTerm = s.toString(); Log.i(TAG, "Text changed " + searchTerm + " starting search thread"); new Thread(this).start(); } public void beforeTextChanged(CharSequence s, int start, int count, int after) { } public void onTextChanged(CharSequence s, int start, int before, int count) { } public void onItemClick(AdapterView parent, View view, int position, long id) { Log.i(TAG, "OnItemClick pos " + position + " id " + id); POI poi = adapter.getPOIItem(position); Uri uri = Uri.parse("geo:" + Util.E6IntToDouble(poi.point.getLatitudeE6()) + "," + Util.E6IntToDouble(poi.point.getLongitudeE6()) + "?z=18"); Log.i(TAG, "Starting a activity for " + uri); Intent mapIntent = new Intent(Intent.ACTION_VIEW, uri); startActivity(mapIntent); } public boolean onItemLongClick(AdapterView parent, View view, int position, long id) { POI poi = adapter.getPOIItem(position); Log.i(TAG, "Long Click Event ID: " + poi.id); Uri uri = null; if (poi.type.equals(POI.BUS_STOP)) { Log.i(TAG, "Its a bus stop"); BusStop busStop = (BusStop) poi; uri = Uri.parse("http://id.southampton.ac.uk/bus-stop/" + busStop.id); } else if (poi.type.equals(POI.BUILDING)) { Log.i(TAG, "Its a buildings"); Building building = (Building) poi; uri = Uri.parse("http://id.southampton.ac.uk/building/" + building.id); } else { Log.e(TAG, "Error in onItemLongClick"); return false; } Log.i(TAG, "Starting a activity for " + uri + " path " + uri.getPath()); Intent busStopIntent = new Intent(Intent.ACTION_VIEW, uri); startActivity(busStopIntent); return true; } public void onLocationChanged(Location location) { Log.i(TAG, "Got location update for FindActivity"); userLocation = Util.locationToGeoPoint(location); if (!searchThread.isAlive()) { searchThread = new Thread(this); searchThread.start(); } } public void onProviderDisabled(String arg0) { } public void onProviderEnabled(String provider) { } public void onStatusChanged(String provider, int status, Bundle extras) { } }