diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/net/cbaines/suma/Bus.java | 7 | ||||
-rw-r--r-- | src/net/cbaines/suma/BusActivity.java | 247 | ||||
-rw-r--r-- | src/net/cbaines/suma/BusSpecificStopView.java | 137 | ||||
-rw-r--r-- | src/net/cbaines/suma/BusStopActivity.java | 7 | ||||
-rw-r--r-- | src/net/cbaines/suma/DataManager.java | 72 | ||||
-rw-r--r-- | src/net/cbaines/suma/DatabaseHelper.java | 2 | ||||
-rw-r--r-- | src/net/cbaines/suma/Preferences.java | 3 | ||||
-rw-r--r-- | src/net/cbaines/suma/StopView.java | 36 |
8 files changed, 495 insertions, 16 deletions
diff --git a/src/net/cbaines/suma/Bus.java b/src/net/cbaines/suma/Bus.java index bddba70..ac2d223 100644 --- a/src/net/cbaines/suma/Bus.java +++ b/src/net/cbaines/suma/Bus.java @@ -19,6 +19,9 @@ package net.cbaines.suma; +import android.os.Parcel; +import android.os.Parcelable; + import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.table.DatabaseTable; @@ -53,13 +56,13 @@ public class Bus { /** * The direction which the bus is travelling. */ - @DatabaseField(canBeNull = false) + @DatabaseField(canBeNull = true) String direction; /** * The destination the bus is travelling towards. */ - @DatabaseField(canBeNull = false, foreign = true) + @DatabaseField(canBeNull = true, foreign = true) BusStop destination; Bus() { diff --git a/src/net/cbaines/suma/BusActivity.java b/src/net/cbaines/suma/BusActivity.java new file mode 100644 index 0000000..44faaa7 --- /dev/null +++ b/src/net/cbaines/suma/BusActivity.java @@ -0,0 +1,247 @@ +package net.cbaines.suma; + +import java.io.IOException; +import java.sql.SQLException; +import java.util.Iterator; +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.preference.PreferenceManager; +import android.util.Log; +import android.view.Gravity; +import android.view.View; +import android.widget.CheckBox; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.TextView; + +import com.j256.ormlite.android.apptools.OrmLiteBaseActivity; + +public class BusActivity extends OrmLiteBaseActivity<DatabaseHelper> { + final static String TAG = "BusActivity"; + + private CheckBox U1RouteRadioButton; + private CheckBox U1NRouteRadioButton; + private CheckBox U2RouteRadioButton; + private CheckBox U6RouteRadioButton; + private CheckBox U9RouteRadioButton; + + private TextView busIDTextView; + + private ProgressBar progBar; + private TextView busContentMessage; + private LinearLayout busActivityContentLayout; + + private Bus bus; + private BusStop busStop; + + protected Timetable timetable; + private Timetable visibleTimetable; + + private Context instance; + + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.bus_activity); + instance = this; + + String busID = getIntent().getExtras().getString("busID"); + String busStopID = getIntent().getExtras().getString("busStopID"); + final DatabaseHelper helper = getHelper(); + + try { + List<Bus> 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); + } + + List<BusStop> busStops = helper.getBusStopDao().queryForEq(BusStop.ID_FIELD_NAME, busStopID); + busStop = null; + 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); + } + + U1RouteRadioButton = (CheckBox) findViewById(R.id.radio_u1); + U1NRouteRadioButton = (CheckBox) findViewById(R.id.radio_u1n); + U2RouteRadioButton = (CheckBox) findViewById(R.id.radio_u2); + U6RouteRadioButton = (CheckBox) findViewById(R.id.radio_u6); + U9RouteRadioButton = (CheckBox) findViewById(R.id.radio_u9); + + busIDTextView = (TextView) findViewById(R.id.busActivityBusID); + + progBar = (ProgressBar) findViewById(R.id.busActivityCenterLoadBar); + busContentMessage = (TextView) findViewById(R.id.busActivityMessage); + busActivityContentLayout = (LinearLayout) findViewById(R.id.busActivityContentLayout); + + if (bus.id != null) { + Log.i(TAG, "Bus id is not null (" + bus.id + ") setting busIDTextView"); + busIDTextView.setText(bus.id); + } else { + Log.w(TAG, "Bus id is null?"); + // Might not ever happen + busIDTextView.setText("Unidentified"); + } + + if (bus.route.uniLink) { + Log.i(TAG, "Bus is uniLink"); + if (bus.route.code.equals("U1")) { + U1RouteRadioButton.setVisibility(View.VISIBLE); + U1NRouteRadioButton.setVisibility(View.GONE); + U2RouteRadioButton.setVisibility(View.GONE); + U6RouteRadioButton.setVisibility(View.GONE); + U9RouteRadioButton.setVisibility(View.GONE); + } else if (bus.route.code.equals("U1N")) { + U1RouteRadioButton.setVisibility(View.GONE); + U1NRouteRadioButton.setVisibility(View.VISIBLE); + U2RouteRadioButton.setVisibility(View.GONE); + U6RouteRadioButton.setVisibility(View.GONE); + U9RouteRadioButton.setVisibility(View.GONE); + } else if (bus.route.code.equals("U2")) { + U1RouteRadioButton.setVisibility(View.GONE); + U1NRouteRadioButton.setVisibility(View.GONE); + U2RouteRadioButton.setVisibility(View.VISIBLE); + U6RouteRadioButton.setVisibility(View.GONE); + U9RouteRadioButton.setVisibility(View.GONE); + } else if (bus.route.code.equals("U6")) { + U1RouteRadioButton.setVisibility(View.GONE); + U1NRouteRadioButton.setVisibility(View.GONE); + U2RouteRadioButton.setVisibility(View.GONE); + U6RouteRadioButton.setVisibility(View.VISIBLE); + U9RouteRadioButton.setVisibility(View.GONE); + } else if (bus.route.code.equals("U9")) { + U1RouteRadioButton.setVisibility(View.GONE); + U1NRouteRadioButton.setVisibility(View.GONE); + U2RouteRadioButton.setVisibility(View.GONE); + U6RouteRadioButton.setVisibility(View.GONE); + U9RouteRadioButton.setVisibility(View.VISIBLE); + } else { + Log.e(TAG, "Route not found " + bus.route.code); + } + } + + } catch (NumberFormatException e) { + e.printStackTrace(); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + private class GetTimetableTask extends AsyncTask<String, Integer, Timetable> { + String errorMessage; + + protected void onPreExecute() { + progBar.setVisibility(View.VISIBLE); + } + + protected Timetable doInBackground(String... busStopID) { + Timetable newTimetable = null; + try { + final SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(instance); + + newTimetable = DataManager.getTimetable(instance, bus, busStop, 10); + } 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(); + } catch (Exception e) { + Log.e(TAG, e.getMessage(), e.getCause()); + } + return newTimetable; + } + + protected void onPostExecute(Timetable newTimetable) { + Log.i(TAG, "Got timetable"); + if (newTimetable == null) { + Log.i(TAG, "Its null"); + + progBar.setVisibility(View.GONE); + busContentMessage.setText(errorMessage); + busContentMessage.setVisibility(View.VISIBLE); + } else { + progBar.setVisibility(View.GONE); + timetable = newTimetable; + displayTimetable(timetable); + } + } + } + + private void displayTimetable(Timetable timetable) { + visibleTimetable = (Timetable) timetable.clone(); + + Log.i(TAG, "It contains " + visibleTimetable.size() + " stops"); + + if (timetable.size() == 0) { + busContentMessage.setText("No Busses"); + busContentMessage.setVisibility(View.VISIBLE); + busActivityContentLayout.setGravity(Gravity.CENTER); + } else { + + for (Iterator<Stop> stopIter = visibleTimetable.iterator(); stopIter.hasNext();) { + Stop stop = stopIter.next(); + Log.i(TAG, "Begin filtering, looking at " + stop + " with route " + stop.bus.route.code); + if (stop.bus.route.code.equals("U1")) { + if (!U1RouteRadioButton.isChecked()) { + stopIter.remove(); + } + } else if (stop.bus.route.code.equals("U1N")) { + if (!U1NRouteRadioButton.isChecked()) { + stopIter.remove(); + } + } else if (stop.bus.route.code.equals("U2")) { + if (!U2RouteRadioButton.isChecked()) { + stopIter.remove(); + } + } else if (stop.bus.route.code.equals("U6")) { + if (!U6RouteRadioButton.isChecked()) { + stopIter.remove(); + } + } else if (stop.bus.route.code.equals("U9")) { + if (!U9RouteRadioButton.isChecked()) { + stopIter.remove(); + } + } + } + + if (visibleTimetable.size() == 0) { + busActivityContentLayout.setGravity(Gravity.CENTER); + busContentMessage.setText("No Busses (With the current enabled routes)"); + busContentMessage.setVisibility(View.VISIBLE); + busTimeList.setVisibility(View.GONE); + } else { + busTimeList.setVisibility(View.VISIBLE); + busContentMessage.setVisibility(View.GONE); + TimetableAdapter adapter; + if ((adapter = (TimetableAdapter) busTimeList.getAdapter()) != null) { + adapter.updateTimetable(visibleTimetable); + } else { + adapter = new TimetableAdapter(this, visibleTimetable); + busTimeList.setAdapter(adapter); + } + busActivityContentLayout.setGravity(Gravity.TOP); + } + } + } +} diff --git a/src/net/cbaines/suma/BusSpecificStopView.java b/src/net/cbaines/suma/BusSpecificStopView.java new file mode 100644 index 0000000..1997e4a --- /dev/null +++ b/src/net/cbaines/suma/BusSpecificStopView.java @@ -0,0 +1,137 @@ +/* + * 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.text.DateFormat; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.view.Gravity; +import android.view.View; +import android.view.View.OnClickListener; +import android.view.View.OnLongClickListener; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import com.j256.ormlite.android.apptools.OpenHelperManager; +import com.j256.ormlite.dao.Dao; + +public class BusSpecificStopView extends LinearLayout implements OnClickListener, OnLongClickListener { + + // private final ImageView icon; + + // private static final String TAG = "StopView"; + + private final TextView location; + private final TextView time; + private String onClickMessage = ""; + private final Context context; + + private Stop stop; + + public BusSpecificStopView(Context context, Stop stop) { + super(context); + + this.context = context; + + this.setOrientation(HORIZONTAL); + + location = new TextView(context); + location.setTextSize(22f); + + time = new TextView(context); + time.setTextSize(22f); + time.setGravity(Gravity.RIGHT); + + setStop(stop); + + addView(location, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); + addView(time, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT)); + } + + public void setStop(Stop stop) { + + // Log.i(TAG, "Time of arival " + stop.arivalTime); + + this.stop = stop; + + location.setText(stop.busStop.description); + time.setText(stop.getTimeToArival()); + + DatabaseHelper helper = OpenHelperManager.getHelper(context, DatabaseHelper.class); + + try { + Dao<Bus, Integer> busDao = helper.getBusDao(); + + busDao.refresh(stop.bus); + + if (stop.bus.id != null) { + if (stop.live) { + onClickMessage = "Bus " + stop.bus.toString() + " at " + DateFormat.getTimeInstance(DateFormat.SHORT).format(stop.arivalTime); + } else { + onClickMessage = "Timetabled bus " + stop.bus.toString() + " at " + DateFormat.getTimeInstance(DateFormat.SHORT).format(stop.arivalTime); + } + } else { + if (stop.live) { + onClickMessage = "Unidentified bus (" + stop.bus.getName() + ") at " + DateFormat.getTimeInstance(DateFormat.SHORT).format(stop.arivalTime); + } else { + onClickMessage = "Timetabled bus (" + stop.bus.getName() + ") at " + DateFormat.getTimeInstance(DateFormat.SHORT).format(stop.arivalTime); + } + } + } catch (SQLException e) { + e.printStackTrace(); + } + + this.setOnClickListener(this); + this.setOnLongClickListener(this); + } + + public void onClick(View v) { + Toast.makeText(context, onClickMessage, Toast.LENGTH_SHORT).show(); + + } + + @Override + public boolean onLongClick(View v) { + DatabaseHelper helper = OpenHelperManager.getHelper(context, DatabaseHelper.class); + + try { + Dao<Bus, Integer> busDao = helper.getBusDao(); + + busDao.refresh(stop.bus); + + if (stop.bus.id != null) { + Intent i = new Intent(context, BusActivity.class); + i.putExtra("busID", stop.bus.id); + ((Activity) context).startActivityForResult(i, 0); + } else { + Toast.makeText(context, "Arival prediction not avalible for timetabled buses", Toast.LENGTH_SHORT).show(); + } + + } catch (SQLException e) { + e.printStackTrace(); + } + return false; + } + +} diff --git a/src/net/cbaines/suma/BusStopActivity.java b/src/net/cbaines/suma/BusStopActivity.java index 421a0eb..5928033 100644 --- a/src/net/cbaines/suma/BusStopActivity.java +++ b/src/net/cbaines/suma/BusStopActivity.java @@ -310,12 +310,9 @@ public class BusStopActivity extends OrmLiteBaseActivity<DatabaseHelper> impleme errorMessage = "Error parsing bus times"; e.printStackTrace(); } catch (Exception e) { - if (THROW_ERROR_ON_EXCEPTION) { - throw new RuntimeException(e.getMessage()); - } else { - Log.e(TAG, e.getMessage(), e.getCause()); - } + Log.e(TAG, e.getMessage(), e.getCause()); } + return newTimetable; } diff --git a/src/net/cbaines/suma/DataManager.java b/src/net/cbaines/suma/DataManager.java index 84731ff..634415d 100644 --- a/src/net/cbaines/suma/DataManager.java +++ b/src/net/cbaines/suma/DataManager.java @@ -24,6 +24,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.sql.SQLException; +import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; @@ -550,18 +551,19 @@ public class DataManager { if (bus == null) { bus = new Bus(busID, route, dir); bus.destination = destStop; + busDao.create(bus); } else { bus.destination = destStop; bus.route = route; bus.direction = dir; + busDao.update(bus); } } else { bus = new Bus(null, route, dir); + busDao.create(bus); } - busDao.update(bus); - stop = new Stop(bus, busStop, calender.getTime(), now, live); return stop; @@ -636,6 +638,72 @@ public class DataManager { return timetable; } + public static Timetable getTimetable(Context context, Bus bus, BusStop startStop, int num) throws SQLException, ClientProtocolException, IOException, + JSONException { + + if (helper == null) + helper = OpenHelperManager.getHelper(context, DatabaseHelper.class); + if (busRouteDao == null) + busRouteDao = helper.getBusRouteDao(); + if (busStopDao == null) + busStopDao = helper.getBusStopDao(); + + Timetable timetable = new Timetable(); + + List<BusStop> busStops = new ArrayList<BusStop>(num); + busStops.add(startStop); + + BusRoute route = bus.route; + + for (int i = 0; i < num; i++) { + BusStop nextStop = route.moveInRoute(context, busStops.get(i), bus.direction, 1); + + if (nextStop != null) { + busStops.add(nextStop); + } else { + Log.e(TAG, "nextStop is null"); + } + } + + for (BusStop busStop : busStops) { + + String file = getFileFromServer(busStopUrl + busStop + ".json"); + + JSONObject data = new JSONObject(file); + JSONArray stopsArray = data.getJSONArray("stops"); + + HashSet<BusRoute> busRoutes = new HashSet<BusRoute>(); + busRoutes.add(bus.route); + + Log.i(TAG, "Number of entries " + data.length()); + + Log.i(TAG, "Stops: " + data.getJSONArray("stops")); + + for (int stopNum = 0; stopNum < stopsArray.length(); stopNum++) { + JSONObject stopObj = stopsArray.getJSONObject(stopNum); + + if (stopObj.getString("vehicle").equals(bus.id)) { + + Stop stop = getStop(context, stopObj, busRoutes, busStop); + + if (stop == null) { + Log.w(TAG, "Null stop, skiping"); + continue; + } + + Log.i(TAG, "Found stop for a unidentified " + stop.bus.toString() + " at " + stop.busStop.id + " at " + stop.arivalTime); + + timetable.add(stop); + + } + } + } + + timetable.fetchTime = new Date(System.currentTimeMillis()); + + return timetable; + } + static PathOverlay getRoutePath(InputStream routeResource, int colour, ResourceProxy resProxy) { PathOverlay data = null; diff --git a/src/net/cbaines/suma/DatabaseHelper.java b/src/net/cbaines/suma/DatabaseHelper.java index a72faca..2d8f9d2 100644 --- a/src/net/cbaines/suma/DatabaseHelper.java +++ b/src/net/cbaines/suma/DatabaseHelper.java @@ -40,7 +40,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { private static final String DATABASE_PATH = "/data/data/net.cbaines.suma/databases/"; private static final String DATABASE_NAME = "data.db"; - private static final int DATABASE_VERSION = 38; + private static final int DATABASE_VERSION = 39; private static final String TAG = "DatabaseHelper"; diff --git a/src/net/cbaines/suma/Preferences.java b/src/net/cbaines/suma/Preferences.java index df44729..d73d0ce 100644 --- a/src/net/cbaines/suma/Preferences.java +++ b/src/net/cbaines/suma/Preferences.java @@ -10,7 +10,4 @@ public interface Preferences { static final boolean NON_UNI_LINK_BUS_TIMES_ENABLED_BY_DEFAULT = false; static final String NON_UNI_LINK_BUS_STOPS = "nonUniLinkBusStops"; static final boolean NON_UNI_LINK_BUS_STOPS_ENABLED_BY_DEFAULT = false; - - static final boolean THROW_ERROR_ON_EXCEPTION = false; - } diff --git a/src/net/cbaines/suma/StopView.java b/src/net/cbaines/suma/StopView.java index 68be1f6..0fe3aa1 100644 --- a/src/net/cbaines/suma/StopView.java +++ b/src/net/cbaines/suma/StopView.java @@ -22,10 +22,13 @@ package net.cbaines.suma; import java.sql.SQLException; import java.text.DateFormat; +import android.app.Activity; import android.content.Context; +import android.content.Intent; import android.view.Gravity; import android.view.View; import android.view.View.OnClickListener; +import android.view.View.OnLongClickListener; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; @@ -33,7 +36,7 @@ import android.widget.Toast; import com.j256.ormlite.android.apptools.OpenHelperManager; import com.j256.ormlite.dao.Dao; -public class StopView extends LinearLayout implements OnClickListener { +public class StopView extends LinearLayout implements OnClickListener, OnLongClickListener { // private final ImageView icon; @@ -44,6 +47,8 @@ public class StopView extends LinearLayout implements OnClickListener { private String onClickMessage = ""; private final Context context; + private Stop stop; + public StopView(Context context, Stop stop) { super(context); @@ -68,6 +73,8 @@ public class StopView extends LinearLayout implements OnClickListener { // Log.i(TAG, "Time of arival " + stop.arivalTime); + this.stop = stop; + name.setText(stop.bus.getName()); time.setText(stop.getTimeToArival()); @@ -88,8 +95,7 @@ public class StopView extends LinearLayout implements OnClickListener { if (stop.live) { onClickMessage = "Unidentified bus (" + stop.bus.getName() + ") at " + DateFormat.getTimeInstance(DateFormat.SHORT).format(stop.arivalTime); } else { - onClickMessage = "Timetabled bus (" + stop.bus.getName() + ") at " - + DateFormat.getTimeInstance(DateFormat.SHORT).format(stop.arivalTime); + onClickMessage = "Timetabled bus (" + stop.bus.getName() + ") at " + DateFormat.getTimeInstance(DateFormat.SHORT).format(stop.arivalTime); } } } catch (SQLException e) { @@ -97,6 +103,7 @@ public class StopView extends LinearLayout implements OnClickListener { } this.setOnClickListener(this); + this.setOnLongClickListener(this); } public void onClick(View v) { @@ -104,4 +111,27 @@ public class StopView extends LinearLayout implements OnClickListener { } + @Override + public boolean onLongClick(View v) { + DatabaseHelper helper = OpenHelperManager.getHelper(context, DatabaseHelper.class); + + try { + Dao<Bus, Integer> busDao = helper.getBusDao(); + + busDao.refresh(stop.bus); + + if (stop.bus.id != null) { + Intent i = new Intent(context, BusActivity.class); + i.putExtra("busID", stop.bus.id); + ((Activity) context).startActivityForResult(i, 0); + } else { + Toast.makeText(context, "Arival prediction not avalible for timetabled buses", Toast.LENGTH_SHORT).show(); + } + + } catch (SQLException e) { + e.printStackTrace(); + } + return false; + } + } |