package net.cbaines.suma; import java.io.IOException; import java.sql.SQLException; import java.util.HashMap; import java.util.List; import org.apache.http.client.ClientProtocolException; import org.json.JSONException; import android.content.Context; import android.content.SharedPreferences; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.preference.PreferenceManager; import android.util.Log; import android.view.Gravity; import android.view.View; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; import com.j256.ormlite.android.apptools.OrmLiteBaseActivity; public class BusActivity extends OrmLiteBaseActivity implements Preferences { final static String TAG = "BusActivity"; private TextView busIDTextView; private TextView busContentMessage; private LinearLayout busActivityContentLayout; Toast activityToast; /** * The bus this activity is focused on */ private Bus bus; /** * The bus stop this activity is working from */ private BusStop busStop; Runnable refreshData; protected Timetable timetable; private Timetable visibleTimetable; private ListView timetableView; private Context instance; // BusStops and if they are being updated by the handler List busStops; private HashMap tasks = new HashMap(); Handler handler; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.bus_activity); instance = this; Log.i(TAG, "getIntent().getDataString() " + getIntent().getDataString()); String busID; if (getIntent().getDataString().startsWith("http://data")) { String[] uriParts = getIntent().getDataString().split("/"); busID = uriParts[uriParts.length - 1].replace(".html", ""); } else { String[] uriParts = getIntent().getDataString().split("/"); busID = uriParts[uriParts.length - 1]; } String busStopID = getIntent().getExtras().getString("busStopID"); final DatabaseHelper helper = getHelper(); try { List buses = helper.getBusDao().queryForEq(Bus.ID_FIELD_NAME, busID); bus = null; if (buses.size() == 0) { Log.e(TAG, "Bus " + busID + " not found!"); } else if (buses.size() == 1) { bus = buses.get(0); } else if (buses.size() > 1) { Log.e(TAG, "Found more than one bus? " + busID); } helper.getBusRouteDao().refresh(bus.route); busStop = null; if (busStopID != null) { List busStops = helper.getBusStopDao().queryForEq(BusStop.ID_FIELD_NAME, busStopID); if (busStops.size() == 0) { Log.e(TAG, "BusStop " + busStopID + " not found!"); } else if (busStops.size() == 1) { busStop = busStops.get(0); } else if (busStops.size() > 1) { Log.e(TAG, "Found more than one busStop? " + busStopID); } } busIDTextView = (TextView) findViewById(R.id.busActivityBusID); busContentMessage = (TextView) findViewById(R.id.busActivityMessage); busActivityContentLayout = (LinearLayout) findViewById(R.id.busActivityContentLayout); timetableView = (ListView) findViewById(R.id.busActivityTimes); if (bus.id != null) { Log.i(TAG, "Bus id is not null (" + bus.id + ") setting busIDTextView"); busIDTextView.setText(bus.id + " " + bus.getName()); } else { Log.w(TAG, "Bus id is null?"); // Might not ever happen busIDTextView.setText("Unidentified"); } } catch (NumberFormatException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } busStops = bus.route.getRouteSection(instance, bus.direction); Log.i(TAG, "Got " + busStops.size() + " bus stops for this bus"); if (bus.destination != null) { Log.i(TAG, "Bus destination is " + bus.destination); } else { Log.i(TAG, "Bus destination is null"); } /* * for (int i = 0;; i++) { BusStop nextStop = bus.route.moveInRoute(instance, busStops.get(i), bus.direction, 1); * * if (nextStop.equals(busStop) || (bus.destination != null && bus.destination.equals(nextStop))) { break; } * * busStops.add(nextStop); busStopsActive.add(false); * * if (busStops.size() > 50) { Log.e(TAG, "Got more than 50 bus stops"); break; } } */ refreshData = new Runnable() { public void run() { for (int num = timetableView.getFirstVisiblePosition(); num < timetableView.getLastVisiblePosition(); num++) { Stop stop = timetable.get(num); GetTimetableStopTask task = tasks.get(busStops.get(num)); if (stop.timeOfFetch == null || (stop.timeOfFetch.getTime() - System.currentTimeMillis()) > 20000) { if (task != null) { if (task.getStatus() == AsyncTask.Status.FINISHED) { task = null; } } if (task == null) { task = new GetTimetableStopTask(); BusStop[] str = { stop.busStop }; task.execute(str); tasks.put(stop.busStop, task); } } } handler.postDelayed(refreshData, 50000); } }; } public void onResume() { super.onResume(); SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this); if (sharedPrefs.getBoolean(UNI_LINK_BUS_TIMES, UNI_LINK_BUS_TIMES_ENABLED_BY_DEFAULT) || sharedPrefs.getBoolean(NON_UNI_LINK_BUS_TIMES, NON_UNI_LINK_BUS_TIMES_ENABLED_BY_DEFAULT)) { Log.i(TAG, "Live Times enabled"); timetable = (Timetable) getLastNonConfigurationInstance(); handler = new Handler(); if (timetable == null) { Log.i(TAG, "No Previous timetable"); timetable = new Timetable(); for (int i = 0; i < busStops.size(); i++) { timetable.add(new Stop(bus, busStops.get(i), null, null, false)); } Log.v(TAG, "Finished adding placeholder stops"); } else { Log.i(TAG, "Displaying previous timetable"); } displayTimetable(timetable); handler.postDelayed(refreshData, 500); } else { Log.i(TAG, "Live Times Disabled"); busContentMessage.setText("Live bus times disabled"); busContentMessage.setVisibility(View.VISIBLE); } } public void onPause() { if (handler != null) { // BusTimes are enabled handler.removeCallbacks(refreshData); for (GetTimetableStopTask task : tasks.values()) { if (task != null) { task.cancel(true); } } Log.i(TAG, "Stoping refreshing timetable data"); } super.onPause(); } private class GetTimetableStopTask extends AsyncTask { private String errorMessage; private BusStop busStop; private int position; protected void onPreExecute() { // progBar.setVisibility(View.VISIBLE); } protected Stop doInBackground(BusStop... busStopArray) { busStop = busStopArray[0]; position = busStops.indexOf(busStop); Stop stop = null; try { Log.i(TAG, "Fetching stop for busStop " + position); stop = DataManager.getStop(instance, bus, busStop); if (stop == null) { stop = new Stop(bus, busStop, null, null, false); } Log.i(TAG, "Finished fetching stop for busStop " + position); } catch (SQLException e) { errorMessage = "Error message regarding SQL?"; e.printStackTrace(); } catch (ClientProtocolException e) { errorMessage = "ClientProtocolException!?!"; e.printStackTrace(); } catch (IOException e) { errorMessage = "Error fetching bus times from server, are you connected to the internet?"; e.printStackTrace(); } catch (JSONException e) { errorMessage = "Error parsing bus times"; e.printStackTrace(); } return stop; } protected void onPostExecute(Stop stop) { // Log.i(TAG, "Got timetable"); if (stop == null) { Log.i(TAG, "Its null"); busContentMessage.setText(errorMessage); busContentMessage.setVisibility(View.VISIBLE); } else { synchronized (timetable) { timetable.set(position, stop); displayTimetable(timetable); } } } } private void displayTimetable(Timetable timetable) { visibleTimetable = (Timetable) timetable.clone(); // Log.i(TAG, "Displaying timetable, it contains " + // visibleTimetable.size() + " stops"); if (timetable.size() == 0) { busContentMessage.setText("No Busses"); busContentMessage.setVisibility(View.VISIBLE); busActivityContentLayout.setGravity(Gravity.CENTER); } else { if (visibleTimetable.size() == 0) { busActivityContentLayout.setGravity(Gravity.CENTER); busContentMessage.setText("No Busses (With the current enabled routes)"); busContentMessage.setVisibility(View.VISIBLE); timetableView.setVisibility(View.GONE); } else { timetableView.setVisibility(View.VISIBLE); busContentMessage.setVisibility(View.GONE); BusSpecificTimetableAdapter adapter; if ((adapter = (BusSpecificTimetableAdapter) timetableView.getAdapter()) != null) { adapter.updateTimetable(visibleTimetable); } else { adapter = new BusSpecificTimetableAdapter(this, visibleTimetable); timetableView.setAdapter(adapter); if (busStop != null) { Log.i(TAG, "Moving to position of " + busStop.description + " which is " + busStops.indexOf(busStop)); timetableView.setSelection(busStops.indexOf(busStop)); } } busActivityContentLayout.setGravity(Gravity.TOP); } } } }